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.

Другие вопросы по тегам