Таблица поиска Ada не работает при вызове Ada из C - PullRequest
0 голосов
/ 23 ноября 2018

Я работаю над кодом Ada, который мне нужно вызвать из C, и я столкнулся с проблемой, которую не могу решить и не знаю, почему это происходит.

Вот тестпроект для иллюстрации проблемы:

lookup.ads

with Interfaces.C; use Interfaces.C;

package lookup is
    procedure Printf(str : in Interfaces.C.char_array; i : in Positive);
    pragma Import(C, printf, "printf");

    procedure PrintLookup;
    pragma Export(C, PrintLookup, "print_lookup");
end lookup;

lookup.adb

with Interfaces.C; use Interfaces.C;

package body lookup is

    -- Month_Length : constant array (1..12) of Positive := (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

    Month_Length : constant array (1..12) of Positive := (4 | 6 | 9 | 11 => 30, 2 => 28, others => 31);

    procedure PrintLookup is
    begin

        printf("Month_Length(5): %d"&To_C(ascii.LF)&To_C(ascii.NUL), Month_Length(5));

    end PrintLookup;

end lookup;

main.adb

with lookup;

procedure main is
begin
    lookup.PrintLookup;
end main;

main.c

extern void print_lookup();

int main()
{
    print_lookup();
    return 0;
}

И у меня есть простой make-файл для его сборки:

BUILD=ada

GM=gnatmake
CC=gcc
LIB=-L/usr/lib/gcc/i686-linux-gnu/4.9/adalib


ifeq ($(BUILD),ada)
main:
    $(GM) lookup.adb main.adb
else
main: lookup.o main.o
    $(CC) $(LIB) lookup.o main.o -o $@ -lgnat

lookup.o:
    $(GM) lookup.adb

main.o:
    $(CC) -c main.c
endif


.PHONY: clean
clean:
    rm -f lookup.ali lookup.o
    rm -f main.ali main.o
    rm -f main

Makefile сгенерирует исполняемый файл с именем main .Если переменная BUILD в первой строке make-файла установлена ​​в ada , она будет использовать Ada main.adb , в противном случае - C main.c

Теперь возникает проблема: если в lookup.adb я использую первый вариант массива Month_Length (который закомментированпрямо сейчас), я получаю следующий вывод для обеих сетей, который является правильным:

Month_Length (5): 31

Но в случае другого массива (которыйназывается таблицей поиска), вариант C возвращает 0:

Month_Length (5): 0

Кто-нибудь имеет представление, почему массив таблицы поиска возвращает 0, когдазвонил из C?Кто-нибудь сталкивался с этой проблемой?Что мне не хватает?Я ценю вашу помощь.

Ответы [ 2 ]

0 голосов
/ 24 ноября 2018

В качестве дополнения я вспомнил, что была альтернатива, которая автоматически выполняла бы вызов init ().

Саймон Райт указал свой подробный ответ на этот вопрос

Когда загружается DLL, Windows систематически вызывает процедуру под названием DllMain.Следовательно, было бы возможно вызвать adainit напрямую из DllMain, не предоставляя явную процедуру инициализации.К сожалению, невозможно вызвать adainit из DllMain, если у вашей программы есть задачи уровня библиотеки, потому что доступ к точке входа DllMain сериализуется системой (то есть, только один поток может выполнить «через» ее одновременно),Это означает, что во время выполнения GNAT тупиковая ситуация ожидает завершения только что созданной задачи для ее инициализации.

см. эту ссылку

можно также посмотретьпри детальном подходе здесь

0 голосов
/ 23 ноября 2018

Как Врумфондель , упомянутый в комментарии, adainit должен быть вызван для инициализации ADA.Вот модификации, которые я сделал, чтобы заставить это работать:

Вот файл сборки:

BUILD=c

GM=gnatmake
GB=gnatbind
CC=gcc
LIB=-L/usr/lib/gcc/i686-linux-gnu/4.9/adalib


ifeq ($(BUILD),ada)
main:
    $(GM) lookup.adb main.adb
else
main: lookup.o main.o
    $(CC) $(LIB) lookup.o b~lookup.o main.o -o $@ -lgnat

lookup.o:
    $(GM) lookup.adb
    $(GB) -n lookup.ali
    $(GM) b~lookup.adb

main.o:
    $(CC) -c main.c
endif


.PHONY: clean
clean:
    rm -f lookup.ali lookup.o
    rm -f b~lookup.*
    rm -f main.ali main.o
    rm -f main

gnatbind создает b ~ lookup.ads и b ~ lookup.adb файлы, которые будут содержать функции adainit () и adafinal () , затем я собрал их с помощью gnatmake (мне пришлось строить, потому что я не использую gnatlink ), и я включил сгенерированный файл b ~ lookup.o в часть ссылки.

main.c пришлось изменить следующим образом (просто вызывая функции init и final до и после вызова ADA):

extern void print_lookup();
extern void adainit();
extern void adafinal();

int main()
{
    adainit();
    print_lookup();
    adafinal();

    return 0;
}

Остальное остается тем же.

...