2

我需要一个能够在我的 Ada 主线中调用函数的 Visual Studio C++ DLL。Ada 代码有一个函数规范,例如

package offset is
    function GET_OFFSET return integer;
    pragma Export (Stdcall, GET_OFFSET, "fnAdaOffset");
end offset;

然后,C++ 函数将调用 Ada 方法,如下所示:

typedef int (*tdAdaOffset)(void);
tdAdaOffset _ptAdaOffset = NULL;

int AdaOffset()
{
   if (_ptAdaOffset == NULL)
   {
      _ptAdaOffset = (tdAdaOffset)GetProcAddress(GetModuleHandle(NULL), "fnAdaOffset@0");
      if (_ptAdaOffset == NULL)
         throw "Function not found";
   }
   return (*_ptAdaOffset)();
}

我相信这会奏效。我遇到的问题是 Ada 拒绝在可执行文件中将函数 GET_OFFSET 标记为外部,即执行 dumpbin /exports ada.exe 显示没有导出函数。

我已经阅读了各种解决方案,例如--version-script for the linker,但我的链接器似乎太旧了,无法了解此开关。

另一个有希望的选项是将 -shared 添加到链接步骤,但是虽然现在这会公开功能,但它也会将输出文件更改为 DLL(以 .EXE 作为其扩展名(!)),所以这也没有用。

在我升级我的工具链之前,我是否可以尝试另一个链接器开关,或任何其他建议?

4

1 回答 1

2

您需要告诉链接器从可执行文件中导出符号。ld有一个选项--export-dynamic,但仅适用于 ELF 目标

请注意,此选项特定于 ELF 目标端口。PE 目标支持从 DLL 或 EXE 导出所有符号的类似功能;请参阅下面对 --export-all-symbols 的描述。

因此,在 Windows 上,您需要使用--export-all-symbols.

根据您编译 Ada 代码的方式,您可能需要通过编译器命令 ( gcc) 传递此选项。要告诉gcc链接器将使用某个选项,请在它前面加上前缀,-Wl然后给出以逗号分隔的链接器选项。在这种情况下,您最终会得到-Wl,--export-all-symbols.

如果您使用 GPRBuild,.gpr文件的相关部分将如下所示:

package Linker is
  for Default_Switches ("Ada") use ("-Wl,--export-all-symbols");
end Linker;

旁注:

  • 请注意,C++int不一定与 Ada 相同Integer,您应该使用Interfaces.C.intAda 中的返回类型。
  • 调用约定必须匹配。Stdcallin Ada 匹配__stdcallC++ 中的显式。如果__stdcallC++ 代码中没有,请改用CAda 中的调用约定。
于 2020-09-21T20:01:36.880 回答