Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows VB-隐式链接DLL_Windows_Multithreading_Visual C++_Dll_Vb6 - Fatal编程技术网

Windows VB-隐式链接DLL

Windows VB-隐式链接DLL,windows,multithreading,visual-c++,dll,vb6,Windows,Multithreading,Visual C++,Dll,Vb6,我正在使用VB6图形界面,需要隐式链接到DLL 这样做的动机来自于我的努力。所讨论的DLL使用静态TLS,\uuu declspec(thread),当然,当使用LoadLibrary显式链接DLL时,这会非常失败 我真的希望避免修改DLL,那么有人知道如何欺骗VB6可执行文件隐式链接到特定的DLL吗?为DLL创建一个IDL文件,在子句中描述导出的函数 使用MIDL编译器编译并引用VB6项目(项目-引用)中生成的tlb文件。 并删除所有Declare函数s tlb文件仅用于编译(在本例中),您不

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

这样做的动机来自于我的努力。所讨论的DLL使用静态TLS,
\uuu declspec(thread)
,当然,当使用LoadLibrary显式链接DLL时,这会非常失败


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

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

使用MIDL编译器编译并引用VB6项目(项目-引用)中生成的tlb文件。
并删除所有
Declare函数
s


tlb文件仅用于编译(在本例中),您不必将其包含在安装程序中。

以下是从标准操作系统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}";
        ...
    }
}

多亏了格斯伯格和大卫·赫弗南的帮助,我终于解决了这个问题

这里是用于生成.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);
        };
    };
要编译它,请使用VisualStudio命令提示符中的命令“midl”

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

在VB6项目的project->References下,可以添加.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文件中,应将更正字符串作为
LPSTR myStr
传递给函数

2) VB6在创建.exe之前不会链接DLL。但如果DLL未链接,则其函数不可见。因此,必须在IDL文件中包含VB6项目中使用的隐式链接DLL的所有功能


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

我已经编辑了问题和标记。我希望你同意。我这样做是为了提高你得到好答案的机会!我不知道如何做的细节,甚至不知道它是否会起作用,但我的直觉告诉我它应该起作用。@David,是的,我注意到了,我说谢谢!现在更清楚的是,我下次将尝试遵循您的模型。这是一个好主意,但我认为VB6仍将动态加载库。@GSerg我不熟悉IDL文件和MIDL编译器,因此我需要一些时间来完成它(现在我正在学习IDL文件是什么)。当我完成后,我会给你一个反馈。非常感谢。@Beppe我专门学习IDL来做这个把戏。当你专注于你需要的领域时,这很容易。MSDN文章末尾的IDL示例基本上是您需要的所有IDL代码。@我尝试过,但一旦我删除
声明函数
s,编译器就会说这些函数没有定义。@Beppe
String
VB。在IDL中,我使用了
LPSTR
,它本质上是
char*
。感谢您的回复!我只是对具有我定义的类型的变量有问题,比如:
int myFunct([in]myStruct data)编译器说:
语法错误:在“myStruct”附近需要一个类型规范。
。你知道如何解决这个问题吗?感谢您必须在IDL中包含该结构(示例已更新),或者您可以将其声明为
long myFunct([in]long data)
,并使用
myFunct VarPtr(uData)
在VB6中调用它。您可以在IDL文件中发布一个包含该结构的示例吗?谢谢这很奇怪,一切都应该在不创建exe的情况下工作,而且您也应该能够调试。无法调试的唯一情况是在tlb中使用不同的调用约定,例如
\uu cdecl
。我建议你下载著名的软件,并用它玩——你会看到一切正常。要从tlb中提取IDL源代码,可以使用任何适当的工具,例如。尽管我能发现的唯一区别是
\uu stdcall
\u stdcall
@GSerg,但我试图修复您发现的差异,但它仍然在IDE中崩溃。关于Windows API tlb,您知道它是否包含使用
\uu declspec(线程)
变量的函数吗?啊。我想这也算是一种不同的通话习惯。家伙。