Windows VB-隐式链接DLL
我正在使用VB6图形界面,需要隐式链接到DLL 这样做的动机来自于我的努力。所讨论的DLL使用静态TLS,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文件仅用于编译(在本例中),您不
\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,编译器就会说这些函数没有定义。@BeppeString
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(线程)
变量的函数吗?啊。我想这也算是一种不同的通话习惯。家伙。