在C ++中使用delphi库 [英] Using delphi library in C++

查看:174
本文介绍了在C ++中使用delphi库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这在很多地方已经在部分讨论过了,但是对我来说还是没有用的。



我有一个从delphi源代码编译的dll,它导出一个函数两个名称,使用

 >> dumpbin / EXPORTS MyLibrary.dll  

我得到以下输出:

  ... 
17 3 00070A88 MyFunction
...
46 24 00070A88 _MyFunction @ 48
...

所以我创建了一个名为MyLibrary.def的文件,具有以下内容:

  EXPORTS 
MyFunction
_MyFunction @ 48

并使用

 >> lib /def:MyLibrary.def /OUT:MyLibrary.lib / MACHINE:x86  

使用dumpbin检查新的lib文件,我看到如下:

  ... 
_MyFunction
...
__MyFunction @ 48
...

所以不知何故的lib应用程序lication在函数名前添加一个下划线。 (为什么?)



然后,我尝试在c ++程序中使用此函数,使用Microsoft Visual Studio C ++ 2010 Express进行编译(使用lib文件):

  // MyLibrary.h 
#define DllImport(Type)__declspec(dllimport)Type __stdcall

extern CDllImport(void)MyFunction(...);



  // main.cpp 
#import MyLibrary.h

...
MyFunction(....);
...

现在应该可以工作,只要我能找到,但是我得到以下链接器错误:

  ...错误LNK2001:未解决的外部异常__imp__MyFunction @ 48。 

我不明白为什么会出错(我不会明白整个事情是如何工作的) 。)但是我尝试了另外两件事情。


  1. 将MyLibrary.h中的函数和MyFunction的main.h重命名为_MyFunction

    • 结果:它的工作原理但为什么?我不想依赖这个,因为事情显然是错误的。
       


  2. 将我的功能重命名为MyFunction并删除def-File中的下划线,再次生成lib文件并尝试编译

    • 结果:编译成功,但是当启动程序时,我得到




  
MyApp - 找不到入口点
------------ ---------------
程序入口点MyFunction @ 48在动态链接库MyLibrary.dll中找不到

我认为需要更深入地了解lib工具和链接器的内部工作,但是目前为止找不到任何这方面的信息。

解决方案

KB131313 解释了一个问题,您将面临尝试使用 lib 实用程序:


只有一个.DEF文件才能从没有源代码或对象模块的.DLL创建导入库,如果.DLL通过C接口导出函数。具体来说,函数需要被声明为使用C调用约定。


您的函数使用stdcall而不是cdecl,因为我们可以从函数名中的 @ 中得知。然而,知识库文章解释了如何做:


  1. 声明函数就像在C ++中一样,但是对于导出,而不是导入



    您已经做到了这一点。你有通话约定权利,但最终的 @ 48 意味着它需要有48个字节的参数。该函数将期望将该数据推送到堆栈,并且在返回之前,该函数会弹出很多关闭。您在声明中使用 ... 与此不兼容。



    如果您不知道具体的参数列表应该是真的,然后继续,然后定义12 int 参数,所以至少堆栈结构将是正确的。 (但是如果你不知道这个列表应该是什么样的,那么你已经很接近注定了。)


  2. 在C ++中编写一个虚拟实现。



    实现可以是空的。唯一的要求是代码编译和链接。


  3. 从该虚拟代码编译您自己的MyLibrary.dll 版本。 / p>

    确保它与原始DLL兼容。运行 dumpbin ,看到它导出至少一个版本的原始DLL中看到的函数名称。 (你不需要这两个;你的程序只会使用其中一个名字,而正如 dumpbin 输出显示的,两个名字都转到二进制文件中的相同位置,所以您的程序最终使用哪个名称并不重要。)


  4. 丢弃DLL并保留LIB文件。

    / li>
  5. 使用lib文件链接到真实的DLL。

如果链接器仍然抱怨它找不到 __ imp_MyFunction @ 48 ,然后从您的声明中删除 dllimport 部分。这应该删除 __ imp _ 前缀,使名称看起来更像Delphi名称。






如果全部失败,您可以使用运行时动态链接而不是加载时间。声明函数的指针类型,然后使用 LoadLibrary GetProcAddress 来访问它。


This has been discussed in parts on many places, but it still wont work for me.

I have a dll compiled from delphi source, which exports one function under two names, inspecting the dll using

>> dumpbin /EXPORTS MyLibrary.dll

i get the following output:

...
17    3 00070A88 MyFunction
...
46   24 00070A88 _MyFunction@48
...

so i created a file called MyLibrary.def with the following content:

EXPORTS
MyFunction
_MyFunction@48

And generated an import library using

>> lib /def:MyLibrary.def /OUT:MyLibrary.lib /MACHINE:x86

Inspecting the new lib-file with dumpbin i see the following:

...
_MyFunction
...
__MyFunction@48
...

So somehow the lib application added one underscore in front of the function name. (why?)

Then i try to use this function in a c++ program, compiling with Microsoft Visual Studio C++ 2010 Express (using the lib file):

// MyLibrary.h
# define DllImport(Type) __declspec (dllimport) Type __stdcall

extern "C" DllImport(void)MyFunction(...);

// main.cpp
#import "MyLibrary.h"

...
MyFunction(....);
...

This should now work, as far as i could find out, but i get the following linker error:

... error LNK2001: Unresolved external sympol "__imp__MyFunction@48".

I don't understand why this goes wrong (i dont realy understand how the whole thing works ...) but i tried two more things.

  1. Renamed my function in MyLibrary.h and main.h from MyFunction to _MyFunction
    • Result: it works! But why? I dont want to rely on this, since something is obviously wrong.  
  2. Renamed my function back to MyFunction and removed the underscore in the def-File, generated the lib file again and tried to compile
    • Result: compilation succeeds, but when starting the program i get


MyApp - Entry Point Not Found
---------------------------
The procedure entry point MyFunction@48 could not be located
in the dynamic link library MyLibrary.dll. 

I think one needs a deeper understanding of the inner working of the lib tool and the linker, but i couldn't find any information about this so far.

解决方案

KB131313 explains one problem you'll face trying to use the lib utility for this:

The only time you can use a .DEF file to create an import library from a .DLL for which you do not have the source code or object modules is if the .DLL exports functions via a C interface. Specifically, the functions need to have been declared to use the C calling convention.

Your functions uses stdcall, not cdecl, as we can tell from the @ in the function name. Nevertheless, the KB article explains what to do instead:

  1. Declare the function as it would be in C++, but for export instead of for import.

    You've already done that, mostly. You have the calling convention right, but the @48 on the end means it needs to have 48 bytes' worth of parameters. The function will expect to have that data pushed on to the stack, and before it returns, the function will pop that much off. Your use of ... in the declaration is incompatible with that.

    If you don't know what the specific argument list should really be, then go ahead and just define 12 int parameters, so at least the stack structure will be right. (But if you don't know what the list should really be, you're pretty close to doomed anyway.)

  2. Write a dummy implementation in C++.

    The implementation can be empty. The only requirement is that the code compiles and links.

  3. Compile your own version of MyLibrary.dll from that dummy code.

    Make sure it's compatible with the original DLL. Run dumpbin on it and see that it exports at least one version of the function names you saw in the original DLL. (You don't need both; your program is only going to use one of the names, and as the dumpbin output shows, both names go to the same location in the binary, so it doesn't matter which name your program ends up using.)

  4. Throw away the DLL and keep just the LIB file.

  5. Use the lib file to link with the real DLL.

If the linker still complains that it cannot find __imp_MyFunction@48, then remove the dllimport part from your declaration. That should remove the __imp_ prefix, making the name look more like the Delphi name.


If all else fails, you can use run-time dynamic linking instead of load-time. Declare a pointer type for the function, and then use LoadLibrary and GetProcAddress to get access to it.

这篇关于在C ++中使用delphi库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆