MS Visual C c++编译DLL供Delphi使用

MS Visual CC++ Compiling DLL for use by Delphi?

本文关键字:Delphi 使用 DLL 编译 Visual c++ MS      更新时间:2023-10-16

我的经验是Delphi XE2,我不熟悉MS Visual C/c++。我正试图将一些MS Visual c++代码编译成我可以从Delphi使用的DLL。

编译后的DLL导出函数无法在Delphi中找到。

使用十六进制编辑器,DLL导出表看起来像以下片段,没有NULL终止的函数名(NULL ASCII字符定位在eol "Z"后面):

      ?MM_End@@YAH_N@Z
      ?MM_GetCurrentPosition@@YAHPAN0000@Z
      ?MM_GetWindow@@YAHPAN000@Z
      ?MM_MarkGetLinkFile@@YAHPAXPADH@Z
      ?MM_Start@@YAH_N@Z

c++头代码看起来像这样:

    ...
    #define MMAPI_API __declspec(dllexport)
    ...
    MMAPI_API int MM_Start(bool run_mmnav);
    MMAPI_API int MM_End(bool close_mmnav);
    ...

参考https://msdn.microsoft.com/en-AU/library/dt232c9t%28v=vs.90%29.aspx。我已经尝试了__stdcall和_cdecl的几种变体,但无法让MS Visual c++编译具有NULL终止字符串的导出表。

您正试图通过猜测来逆向工程一个文档完备的格式。PE格式是已知的并有文档记录。你试图用十六进制编辑器来逆转它是没有意义的。您根本不需要理解格式。使用现有工具列出导出的函数。例如,从MS工具链或依赖项查看器中转储。

一旦你列出了这些导出,你会发现它们已经被导出到它们的c++名称下。名称混淆是c++编译器在用于链接的函数名中编码函数签名的方式。Mangling的设计目的是允许c++工具链支持重载函数,并继续使用C风格的链接器技术。

您将看到一个导出符号列表,如下所示:

  • ?MM_Start@@YAH_N@Z
  • ?MM_End@@YAH_N@Z
  • 等。

把这些东西拿给销售人员看看,以确认它们是你所期望的。以上符号排列如下:

int __cdecl MM_Start(BOOL)
int __cdecl MM_End(BOOL)

如果您愿意,可以使用这些名称导入它们。例如:

function MM_Start(run_mmnav: BOOL): Integer; cdecl;
  external dllname name '?MM_Start@@YAH_N@Z';
function MM_End(run_mmnav: BOOL): Integer; cdecl;
  external dllname name '?MM_End@@YAH_N@Z';

或者您可以选择在编译DLL时禁止导出函数的c++名称混淆。要做到这一点,可以将函数声明包装在extern "C"块中,或者使用.def文件导出函数。