gary hagerty Ответов: 3

Как вернуть строку из библиотеки DLL, написанной на C++, в VB6


Здравствуйте дамы и господа из проекта Code,

Я пытаюсь выяснить, как вернуть строку через функцию, написанную на C++ (используя Visual Studio 2015, а не мной) в VB6.

Пожалуйста, имейте в виду, что строка должна быть передана через функцию, а не как параметр.

У меня есть опыт работы с VB6, но не с C++!

Мне дали статическую библиотеку и заголовочный файл, и кто-то на работе собрал для меня DLL C++, которую я мог бы вызвать.

Проблема, с которой я сталкиваюсь, заключается в том, что когда я вызываю функцию, которая возвращает строку через функцию, она возвращает строку длины 0.

Я бы подошел к человеку на работе по этому поводу, но он сейчас недоступен!

Коды следующим образом:

extern "C" {
VBDLLFUNC(char*) MDNSgetPath();
}

Где #определить VBDLLFUNC(Имя_типа) с атрибутом dllexport имя как __stdcall

//char* getPath();
extern "C" {
VBDLLFUNC(char*) MDNSgetPath() {
return(getPath());
}
}

У меня есть следующее объявление в моем коде VB6:

Объявить Функцию MDNSgetPath Lib "MDTestDLL.dll" () Как Строка

В моем событии загрузки формы я вызываю функцию следующим образом:

Функцию MsgBox "|" &амп; MDNSgetPath &ампер; "|"

Результат, который я получаю обратно, таков: ||

Пожалуйста, посоветуйте

Спасибо

Что я уже пробовал:

Я погуглил, но ничего особенного не нашел.

3 Ответов

Рейтинг:
2

Randor

Привет Гэри,

Здесь есть старая статья о codeproject, которая демонстрирует, как это сделать.

VC++ & VB Inter Process Communication Plus введение в подклассы VB[^]


Рейтинг:
2

Shao Voon Wong

Вернуть BSTR строка из функции C++. Строка VB на самом деле является VC++ BSTR под. Вызов SysAllocString() чтобы выделить a BSTR строка. SysAllocString() принимает в качестве входных данных строку Unicode. Вам нужно преобразовать ваш ASCII char* строка в юникоде wchar_t*. Вам не нужно освобождать BSTR, VB6 освободит его для вас с помощью SysFreeString().

Перед использованием SysAllocString(), вы должны включить OleAuto.h заголовочный файл и библиотека импорта, OleAut32.lib.

#include <OleAuto.h>

#pragma comment(lib, "OleAut32")

extern "C" 
{
	VBDLLFUNC(BSTR) MDNSgetPath() 
	{
		BSTR result = ::SysAllocString(L"Some text");
		return result;
	}
}


Ниже приведена наивная функция для преобразования ASCII в строковый тип Unicode.

#include <string>

std::wstring ToWideString(const std::string& src)
{
    std::wstring result = L"";
    for(size_t i=0; i<src.size(); ++i)
    {
        result += (wchar_t)src[i];
    }
    return result;
}


Ваш новый MDNSgetPath() позвонит тот самый ToWideString() что в свою очередь вызывает ваш getPath().

extern "C" 
{
	VBDLLFUNC(BSTR) MDNSgetPath() 
	{
		BSTR result = ::SysAllocString(ToWideString(getPath()).c_str());
		return result;
	}
}


Финал MDNSgetPath() может быть упрощен в 1 строку путем удаления временного result переменная.

#include <OleAuto.h>

#pragma comment(lib, "OleAut32")

extern "C" 
{
	VBDLLFUNC(BSTR) MDNSgetPath() 
	{
		return ::SysAllocString(ToWideString(getPath()).c_str());
	}
}


gary hagerty

Здравствуйте Сэр,

Большое вам спасибо, это то, что я искал!

Когда я попробовал ваш первый пример выше:

extern "C"
{
VBDLLFUNC(BSTR) MDNSgetPath()
{
BSTR result = ::SysAllocString(L"Некоторый текст");
возвращаемый результат;
}
}

Я получаю следующую строку, возвращенную мне в VB6:

С О М е т е х Т

Пожалуйста, посоветуйте

Спасибо

gary hagerty

Здравствуйте Сэр,

Хорошо, я думаю, что теперь это работает, мне пришлось выполнить следующий шаг, чтобы перенастроить строку на меня, которая находится в формате UNICODE в ANSI:

Тусклый спат как струна

sPath = StrConv(MDNSgetPath, vbFromUnicode)

Еще раз спасибо за вашу помощь, это действительно очень помогло мне

Рейтинг:
2

KarstenK

Работа с _bstr_t это самое лучшее решение. Всегда можно создать новую копию в VB, а не полагаться на возвращенном экземпляре. Это позволяет избежать странных ошибок.

Другое решение состоит в том, чтобы передать некоторый байтовый буфер и затем построить некоторую строку.

VB6 устарел и имеет несовместимый синтаксис к современному VB.net. Поэтому старайтесь не вкладывать свое время и силы в эту технологию.


gary hagerty

Большое вам спасибо за ваш ответ.

Я знаю, что VB6 довольно устарел, но потребовались бы огромные усилия, чтобы реализовать приложение, которое используется 24/7 в VB.NET хотя мне бы этого очень хотелось.

Я не знаком с _bstr_t, но если бы я его использовал, как бы он изменил код?

Dave Kreskowiak

Вы ничего не меняете в своем коде VB6. Вы уже делаете это правильно, и, честно говоря, у вас нет другого способа сделать это.

Код C должен быть изменен, чтобы вернуть строку таким образом, с которым VB6 может работать. Внутренне VB6 использует строки BSTR, с которыми вы можете ознакомиться здесь[^]