如何从可从C++代码调用的 Ada 源代码构建静态库?



我需要构建一个静态库,其中包含一堆用ADA编写的代码,可以从C/C 编写的代码中调用。

我已经通过Internet进行了搜索,并了解了gnatmakegnatbindgnatlink,但仍然无法正确完成工作。

另外,我已经阅读了一些工具,这些工具依赖于某种项目文件。我对这些不感兴趣,我只需要一堆命令即可在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.adsbar.adbs/foo/bar/g)。

编译以下内容:

gnatmake foo bar

绑定:

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;
}

(您的主要位于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

谢谢您的巨大帮助!实际上,它可以与以下makefile一起使用:

ada_libs := -lgnat -lgnarl
cpp_src := ...
ada_src := ...
library.so : $(cpp_src:.cc=.o) adalib.a
    g++ -o $@ $^ $(ada_libs)
$(cpp_src:.cc=.o) : %.o : %.cc
    g++ -c -o $@ $<
$(cpp_src:.cc=.d) : %.d : %.cc
    g++ -MM -MF $@ $^
$(addprefix objects/,$(ada_src:.adb=.o)) : objects/%.o : %.adb
    gnatmake -c -D objects $^
adabind.adb : $(addprefix objects/,$(ada_src:.adb=.o))
    gnatbind -n -o $@ $(^:.o=.ali)
adabind.ali : adabind.adb
    gnatmake -c -D objects $^
adalib.a : adabind.ali
    ar cur $@ $(^:.ali=.o) objects/*.o
include $(cpp_src:.cc=.d)

除此之外,我必须在我的C 文件中声明自己的功能为外部" C"。

非常感谢,我几乎在那里,但错过了链接时包括ADA运行时库(-lgnat -lgnarl)。

最新更新