VB - Связывание DLL неявным способом - PullRequest
3 голосов
/ 04 марта 2011

Я работаю над графическим интерфейсом VB6, и мне нужно сделать неявную ссылку на DLL.

Мотивация для этого взята из моего предыдущего вопроса . Рассматриваемая DLL использует статический TLS, __declspec(thread), и, конечно, это ужасно дает сбой, когда DLL явно связана с использованием LoadLibray.

Я бы действительно хотел избежать изменений в DLL, так кто-нибудь знает, как обмануть исполняемый файл VB6 для неявной ссылки на конкретную DLL?

Ответы [ 3 ]

5 голосов
/ 04 марта 2011

Создайте файл IDL для вашей DLL, который описывает ваши экспортированные функции в предложении module.

Компиляция с помощью компилятора MIDL и ссылка на полученный файл tlb из вашего проекта VB6 (Project - References).
И удалить все Declare Function с.

Файл tlb используется только для компиляции ( в данном случае ), вам не нужно включать его в настройку.

2 голосов
/ 04 марта 2011

Вот пример 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}";
        ...
    }
}
0 голосов
/ 10 марта 2011

Наконец я смог решить проблему благодаря помощи GSerg и Дэвида Хеффернана.

Здесь 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.

...