pragma export 函数在 Ada 可执行文件中不是外部的

pragma export function is not external in Ada executable

我需要一个 Visual Studio C++ DLL 来调用我的 Ada 主线中的函数。 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,但我的 linker 似乎太老了,不知道这个开关。

另一个有前途的选项是将 -shared 添加到 link 步骤,但是虽然现在公开了函数,但它还将输出文件更改为 DLL(扩展名为 .EXE (!)) ,所以这也没有用。

在我升级​​我的工具链之前,是否有另一个 linker switch 我可以尝试,或者任何其他建议?

您需要告诉链接器从可执行文件中导出符号。 ld 有一个选项 --export-dynamic,但是 only works on ELF targets:

Note that this option is specific to ELF targeted ports. PE targets support a similar function to export all symbols from a DLL or EXE ; see the description of --export-all-symbols below.

因此,在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.int 作为 Ada 中的 return 类型。
  • 调用约定必须匹配。 Ada 中的 Stdcall 匹配 C++ 中的显式 __stdcall。如果 C++ 代码中没有 __stdcall,请改用 Ada 中的 C 调用约定。