Как создать статическую библиотеку из исходного кода Ada, которая вызывается из кода C ++?

Мне нужно собрать статическую библиотеку с кучей кода, написанного на Ada, который можно вызывать из кода, написанного на C / C ++.

Я искал через интернет и получил некоторые знания о gnatmake, gnatbind а также gnatlink, но все еще не может сделать работу правильно.

Кроме того, я читал, что есть инструменты, основанные на каком-то файле проекта.
Я не заинтересован в них, мне просто нужно несколько команд, чтобы написать в Makefile,

5

Решение

Этот ответ предполагает, что вы используете цепочку инструментов 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;

или, если вы используете Ada до 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 на протяжении).

Скомпилируйте это:

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

(ваш главный в 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
10

Другие решения

Спасибо вам за большую помощь!
На самом деле, он работал со следующим 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)

Кроме того, я должен был объявить свою функцию как extern «C» в моем файле C ++.

Большое спасибо, я почти был там, но пропустил включение библиотек времени выполнения ada (-lgnat -lgnarl) при компоновке.

2