我需要用一堆用 Ada 编写的代码构建一个静态库,这些代码可以从用 C/C++ 编写的代码中调用。
我通过互联网搜索并了解了一些关于gnatmake
、gnatbind
和gnatlink
的知识,但仍然无法完成工作正确。
此外,我还读到过一些依赖于某种项目文件的工具。
我对那些不感兴趣,我只需要在 Makefile
中编写一堆命令。
最佳答案
此答案假定您使用的是 GCC 工具链。
最大的障碍是 Ada 代码需要详细说明(大致相当于在 C++ 中调用文件级构造函数)。 gnatbind 是执行此操作的工具,您可以使用标志 -L
:
-Lxyz Library build: adainit/final renamed to xyzinit/final, implies -n
[...]
-n No Ada main program (foreign main routine)
例如,考虑 Ada 源 foo.ads
,
package Foo is
procedure Impl
with
Convention => C,
Export,
External_Name => "foo";
end Foo;
或者,如果使用 Ada2012 之前的 Ada,
package Foo is
procedure Impl;
pragma Export (Convention => C, Entity => Impl, External_Name => "foo");
end Foo;
和foo.adb
,
with Ada.Text_IO;
package body Foo is
procedure Impl is
begin
Ada.Text_IO.Put_Line ("I am foo");
end Impl;
begin
Ada.Text_IO.Put_Line ("foo is elaborated");
end Foo;
和一对类似的文件bar.ads
、bar.adb
(整个s/foo/bar/g
)。
编译这些:
gnatmake foo bar
绑定(bind):
gnatbind -Lck -o ck.adb foo.ali bar.ali
(这实际上会生成 ck.ads
以及命名的 ck.adb
;这些是进行详细说明的代码)。
编译细化代码:
gnatmake ck.adb
生成库:
ar cr libck.a ck.o foo.o bar.o
您几乎可以开始了。
C 主程序可能看起来像
#include <stdio.h>
void ckinit(void);
void ckfinal(void);
void foo(void);
void bar(void);
int main()
{
ckinit();
printf("calling foo:\n");
foo();
printf("calling bar:\n");
bar();
ckfinal();
return 0;
}
(您的 main 使用 C++,因此您当然需要 extern "C"{
...)。
你会认为
gcc main.c libck.a
会成功的。但是,libck
在 Ada 运行时调用。在这里 (macOS),这意味着我说
gcc main.c libck.a /opt/gnat-gpl-2016/lib/gcc/x86_64-apple-darwin14.5.0/4.9.4/adalib/libgnat.a
(您可以使用 gcc --print-libgcc-file-name
找到该路径)
生成的可执行文件运行:
$ ./a.out
bar is elaborated
foo is elaborated
calling foo:
I am foo
calling bar:
I am bar
关于c++ - 如何从可从 C++ 代码调用的 Ada 源构建静态库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40870366/