Jan*_*sch 2 c++ delphi import dll
这已经在很多地方进行了部分讨论,但对我来说仍然不起作用。
我有一个从delphi源代码编译的dll,它以两个名称导出一个函数,使用检查dll
>> dumpbin /EXPORTS MyLibrary.dllRun Code Online (Sandbox Code Playgroud)
我得到以下输出:
...
17 3 00070A88 MyFunction
...
46 24 00070A88 _MyFunction@48
...Run Code Online (Sandbox Code Playgroud)
所以我创建了一个名为 MyLibrary.def 的文件,其中包含以下内容:
EXPORTS
MyFunction
_MyFunction@48Run Code Online (Sandbox Code Playgroud)
并使用生成导入库
>> lib /def:MyLibrary.def /OUT:MyLibrary.lib /MACHINE:x86Run Code Online (Sandbox Code Playgroud)
使用 dumpbin 检查新的 lib 文件,我看到以下内容:
...
_MyFunction
...
__MyFunction@48
...
Run Code Online (Sandbox Code Playgroud)
因此,lib 应用程序以某种方式在函数名称前面添加了一个下划线。(为什么?)
然后我尝试在 C++ 程序中使用此函数,使用 Microsoft Visual Studio C++ 2010 Express 进行编译(使用 lib 文件):
// MyLibrary.h
# define DllImport(Type) __declspec (dllimport) Type __stdcall
extern "C" DllImport(void)MyFunction(...);
Run Code Online (Sandbox Code Playgroud)
// main.cpp
#import "MyLibrary.h"
...
MyFunction(....);
...
Run Code Online (Sandbox Code Playgroud)
据我所知,这现在应该可以工作,但是我收到以下链接器错误:
... error LNK2001: Unresolved external sympol "__imp__MyFunction@48".
Run Code Online (Sandbox Code Playgroud)
我不明白为什么会出错(我真的不明白整个事情是如何工作的......)但我又尝试了两件事。
MyApp - Entry Point Not Found
---------------------------
The procedure entry point MyFunction@48 could not be located
in the dynamic link library MyLibrary.dll.
Run Code Online (Sandbox Code Playgroud)
我认为需要更深入地了解 lib 工具和链接器的内部工作原理,但到目前为止我找不到任何有关此的信息。
KB131313解释了您在尝试使用lib该实用程序时会遇到的一个问题:
唯一可以使用 .DEF 文件从没有源代码或对象模块的 .DLL 创建导入库的情况是 .DLL 通过 C 接口导出函数。具体来说,需要声明函数才能使用 C 调用约定。
您的函数使用 stdcall,而不是 cdecl,正如我们从@函数名称中可以看出的那样。不过,知识库文章解释了该怎么做:
像在 C++ 中一样声明该函数,但用于导出而不是用于导入。
大部分你已经做到了。您的调用约定是正确的,但@48最后意味着它需要有 48 个字节的参数。该函数期望将这些数据推送到堆栈上,并且在返回之前,该函数会将这些数据弹出。...您在声明中使用的与此不兼容。
如果您不知道具体的参数列表到底应该是什么,那么就继续定义 12 个int参数,这样至少堆栈结构是正确的。(但如果你不知道这个列表到底应该是什么,那么你就注定要失败了。)
用 C++ 编写一个虚拟实现。
实现可以为空。唯一的要求是代码可以编译和链接。
从该虚拟代码编译您自己的MyLibrary.dll版本。
确保它与原始 DLL 兼容。运行dumpbin它并查看它至少导出您在原始 DLL 中看到的函数名称的一个版本。(您不需要两者;您的程序只会使用其中一个名称,并且如dumpbin输出所示,两个名称都位于二进制文件中的同一位置,因此您的程序最终使用哪个名称并不重要.)
丢弃 DLL,只保留 LIB 文件。
如果链接器仍然抱怨找不到__imp_MyFunction@48,则从dllimport声明中删除该部分。这应该删除__imp_前缀,使名称看起来更像 Delphi 名称。
如果所有其他方法都失败,您可以使用运行时动态链接而不是加载时。声明函数的指针类型,然后使用LoadLibrary和GetProcAddress来访问它。