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

标签 c++ static-libraries ada

我需要用一堆用 Ada 编写的代码构建一个静态库,这些代码可以从用 C/C++ 编写的代码中调用。

我通过互联网搜索并了解了一些关于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.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/

相关文章:

macos - 在 Mac OS 10.8(64 位)上编译 SQLCipher

cross-compiling - GNAT GPL Ada 在为 Raspberry pi 交叉编译时失败将链接错误

ada - 如何保存判别记录的访问类型以供以后使用

c++ - 具有传递引用对象的类会产生编译错误

c++ - 调试器显示的两个相同的调用堆栈不同

c++ - 如何在 Xcode 中使用像 "libstk.a"这样的静态库?

stream - 当从 Ada 中的 Stream 读取数据时,如何调整/匹配记录组件的大小?

c++ - Boost::signals2 - 传递信号槽作为参数

c++ - 当我执行 C++ 程序时如何设置 VSCode 屏幕不会立即消失

ios - 给项目添加斑马线 Xcode 4.5