如何从Ada源构建可从C ++代码调用的静态库? [英] How to build a static library from Ada source that's callable from C++ code?
问题描述
我需要用一堆用Ada编写的代码构建一个静态库,可以从用C / C ++编写的代码中调用这些代码。
I need to build a static library with a bunch of code written in Ada that can be called from code written in C/C++.
我已经搜索了互联网,并且对 gnatmake
, gnatbind
和 gnatlink
有一些了解,但仍然无法正确完成工作。
I've searched through internet and got some knowledge about gnatmake
, gnatbind
and gnatlink
, but still can't get the job done correctly.
此外,我已经阅读了一些依赖某种项目文件的工具。
我对这些都不感兴趣,我只需要一堆命令即可编写 Makefile
。
Also, I've read there are tools that relies upon some kind of project file.
I'm not interested in those, I just need a bunch of commands to write in a Makefile
.
推荐答案
此答案假设您使用的是GCC工具链。
This answer assumes you’re using the GCC toolchain.
最大的障碍是Ada代码需要详细说明(大致,相当于在C ++中调用文件级构造函数)。 gnatbind 是执行此操作的工具,您使用标志 -L
:
The big hurdle is that Ada code needs elaboration (roughly, the equivalent of calling file-level constructors in C++). gnatbind is the tool that does this, and you use the flag -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,
or, if using Ada prior to Ada2012,
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
)。
and a similar pair of files bar.ads
, bar.adb
(s/foo/bar/g
throughout).
编译以下内容:
gnatmake foo bar
绑定:
gnatbind -Lck -o ck.adb foo.ali bar.ali
(这实际上会生成 ck.ads
以及命名为 ck.adb
的代码;这些是进行详细说明的代码。
(this will actually generate ck.ads
as well as the named ck.adb
; these are the code that does the elaboration).
编译详细代码:
gnatmake ck.adb
生成库:
ar cr libck.a ck.o foo.o bar.o
,您几乎可以滚动了。
C主程序可能看起来像
The C main program might look like
#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 {
...,当然)。
(your main is in C++, so you’ll need extern "C" {
..., of course).
您会认为
gcc main.c libck.a
<可以的。但是, libck
在Ada运行时中调用。在这里(macOS),这意味着我说
would do the trick. However, libck
calls in the Ada runtime. Here (macOS), that means I say
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
)
找到该路径,生成的可执行文件将运行:
The resulting executable runs:
$ ./a.out
bar is elaborated
foo is elaborated
calling foo:
I am foo
calling bar:
I am bar
这篇关于如何从Ada源构建可从C ++代码调用的静态库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!