VB - 以隐式方式链接DLL

时间:2011-03-04 15:19:41

标签: windows multithreading visual-c++ dll vb6

我正在使用VB6图形界面,我需要隐式链接到DLL。

这样做的动机来自我previous question。有问题的DLL使用静态TLS,__declspec(thread),当使用LoadLibray明确链接DLL时,这当然会失败。

我真的想避免修改DLL,所以有人知道如何欺骗VB6可执行文件隐式链接到特定的DLL吗?

3 个答案:

答案 0 :(得分:5)

为您的DLL创建一个IDL文件,用于在module子句中描述导出的函数。

使用MIDL编译器编译并从VB6项目中引用生成的tlb文件(项目 - 参考)。
并删除所有Declare Function

tlb文件仅用于编译(在本例中为 ),您不必将其包含在设置中。

答案 1 :(得分:2)

以下是从标准OS dll导入函数的示例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}";
        ...
    }
}

答案 2 :(得分:0)

最后,由于GSerg和David Heffernan的帮助,我能够解决问题。

这里是用于生成.tlb

的IDL
[
    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);
        };
    };

要编译它,请在Visual Studio命令提示符中使用命令“midl”。

生成的.tlb文件应与DLL一起放在VB6项目的同一目录中。

在Project-> References下的VB6项目中,可以添加.tlb文件。

如果一切顺利,按F2,就可以在可用库的列表中注意到“myTypeLib”。

现在可以在VB6项目中调用“myFunc”了!

然而,有两个问题需要指出:

1)VB6和C之间的某些变量类型不兼容。此问题的一个示例由char数组提供。在VB6中,它们被声明为Dim myStr as String,在C中它们通常被声明为char myStr[MAX_DIM];。为了使VB6和C之间的转换成为可能,而不修改DLL,可以在VB6端将字符串声明为Dim myStr as String * 256,而在IDL文件中,应将相应的字符串作为{{1}传递给函数。 }。

2)VB6在创建.exe之前不会链接DLL。但是如果DLL没有链接,那么它的功能是不可见的。出于这个原因,必须在IDL文件中包含必须在VB6项目中使用的隐式链接DLL的所有功能。

此外,出于同样的原因,即使在IDL文件中包含所有功能之后,也无法从IDE运行程序(它将崩溃)以进行调试。运行应用程序的唯一方法是创建.exe。