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

2023-12-28

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

我通过互联网搜索并了解了一些知识gnatmake, gnatbind and 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;

and 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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐