我需要一个 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 ,但我的链接器似乎太旧了,无法了解此开关。
另一个有希望的选择是将 -shared 添加到链接步骤,但是虽然现在公开了函数,但它还将输出文件更改为 DLL(以 .EXE 作为扩展名(!)),因此这也没有用.
在升级工具链之前,我可以尝试另一个链接器开关,或者有其他建议吗?
最佳答案
您需要告诉链接器从可执行文件中导出符号。 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 中的
Stdcall
与 C++ 中的显式__stdcall
相匹配。如果 C++ 代码中没有__stdcall
,请改用 Ada 中的C
调用约定。
关于windows - pragma 导出函数在 Ada 可执行文件中不是外部的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63945894/