VB - Связывание DLL неявным способом
Я работаю над графическим интерфейсом VB6, и мне нужно сделать неявную ссылку на DLL.
Мотивация для этого вытекает из моего предыдущего вопроса. Рассматриваемая DLL использует статический TLS, __declspec(thread)
и, конечно, это ужасно не получается, когда DLL явно связана с помощью LoadLibray.
Я действительно хотел бы избежать изменений в DLL, так кто-нибудь знает, как обмануть исполняемый файл VB6 для неявной ссылки на конкретную DLL?
3 ответа
Создайте файл IDL для вашей DLL, который описывает ваши экспортированные функции в module
пункт.
Скомпилируйте с помощью компилятора MIDL и ссылайтесь на полученный файл tlb из вашего проекта VB6 (Project - References).
И удалить все Declare Function
s.
Файл tlb используется только для компиляции (в данном случае), вам не нужно включать его в настройку.
Вот пример IDL, который импортирует функции из стандартных библиотек ОС
[
uuid(YOURTYPE-LIBG-UIDH-ERE0-000000000000),
version(1.0),
helpstring ("My Type Library 1.0")
]
library MyTypeLib
{
importlib("stdole2.tlb");
typedef struct {
long Data1;
short Data2;
short Data3;
BYTE Data4[8];
} VBGUID;
typedef VBGUID CLSID;
[dllname("OLEAUT32")]
module OleAut32
{
[entry("SysAllocString")]
BSTR SysAllocString([in] long lpStr);
...
};
[dllname("USER32")]
module User32
{
[entry("RegisterClipboardFormatA")]
UINT RegisterClipboardFormat([in] LPSTR lpszFormat);
[entry("FillRect")]
DWORD FillRect([in] DWORD hDC, [in] int lpRect, [in] DWORD hBrush);
...
};
[dllname("BOGUS")]
module Strings
{
const LPSTR CLSID_DsQuery = "{8A23E65E-31C2-11D0-891C-00A024AB2DBB}";
const LPSTR CLSID_DsFindObjects = "{83EE3FE1-57D9-11D0-B932-00A024AB2DBB}";
...
}
}
Наконец, я смог решить проблему благодаря помощи GSerg и David Heffernan.
Здесь IDL будет использоваться для генерации.tlb
[
uuid(12345678-1234-1234-1234-123456789ABC),
version(1.0)
]
library myTypeLib
{
[dllname("myLib.dll")]
module myLib
{
[entry("myFunc")]
int __stdcall myFunc( LPSTR filename_in, LPSTR filename_out, LPSTR ErrMsg);
};
};
Для компиляции используйте команду "midl" в командной строке Visual Studio.
Полученный файл.tlb должен быть помещен в тот же каталог проекта VB6 вместе с DLL.
В проект VB6 в Project->References можно добавить файл.tlb.
Если все прошло хорошо, нажав F2, можно было бы заметить "myTypeLib" в списке доступных библиотек.
Теперь можно вызывать "myFunc" внутри проекта VB6!
Однако следует отметить две проблемы:
1) Некоторые типы переменных несовместимы между VB6 и C. Примером этой проблемы являются массивы символов. В то время как в VB6 они объявлены как Dim myStr as String
в C они обычно объявляются как char myStr[MAX_DIM];
, Чтобы сделать возможным перевод между VB6 и C, без изменения DLL, можно объявить на стороне VB6 строки как Dim myStr as String * 256
в то время как в файле IDL соответствующая строка должна быть передана функции как LPSTR myStr
,
2)VB6 не связывает библиотеки DLL, пока не создан.exe. Но если DLL не связана, то ее функции не видны. По этой причине все функции неявно связанных библиотек DLL, которые должны использоваться в проекте VB6, должны быть включены в файл IDL.
Более того, по той же причине, даже после того, как все функции были включены в файл IDL, будет невозможно запустить программу из IDE (она будет аварийно завершать работу), так как она будет отлаживаться. Единственный способ запустить приложение - создать.exe.