FastCGI с Ada

Я нашел http://support.zeus.com/zws/examples/2005/12/16/hello_world_in_perl_and_c, и эти два примера работают.

Сейчас я пробовал это для Ады и не могу сделать это уже 2 дня.

fcgi_stdio.ads

with Interfaces.C;
with Interfaces.C.Strings;

package fcgi_stdio is
    function FCGI_Accept return Interfaces.C.int;
    pragma Import (C, FCGI_Accept, "FCGI_Accept");

    procedure FCGI_printf (str : Interfaces.C.Strings.chars_ptr);
    pragma Import (C, FCGI_printf, "FCGI_printf");
end fcgi_stdio;

test.adb

with fcgi_stdio;
with Interfaces.C;
with Interfaces.C.Strings;

procedure Test is
begin
    while Integer (fcgi_stdio.FCGI_Accept) >= 0 loop
        fcgi_stdio.FCGI_printf (Interfaces.C.Strings.New_String ("Content-Type: text/plain" & ASCII.LF & ASCII.LF));
        fcgi_stdio.FCGI_printf (Interfaces.C.Strings.New_String ("Hello World from Ada!" & ASCII.LF));
    end loop;
end Test;

Когда я запускаю его в консоли, я получаю следующую ошибку:

$ ./test
raised STORAGE_ERROR : stack overflow or erroneous memory access

Apache error_log показывает:

Premature end of script headers: test

Кто-нибудь знает, как я могу заставить его работать?


person user1091344    schedule 12.01.2013    source источник


Ответы (1)


Экспериментируя с Mac OS X, кажется, что проблема в том, что FCGI_printf() - это функция varargs. Он вызывает FCGI_fprintf(), также varargs:

int FCGI_fprintf(FCGI_FILE *fp, const char *format, ...)
{
    va_list ap;
    int n = 0;
    va_start(ap, format);          <------ crash here

В Ada нет стандартного способа указания функций varargs, и GNAT также не имеет способа, определяемого реализацией.

В документации GNAT говорится, что решение состоит в том, чтобы предоставить оболочку C для функции varargs:

#include <fcgi_stdio.h>
int FCGI_printf_wrapper(const char *msg)
{
  return FCGI_printf(msg);
}

и импортируем обертку:

procedure FCGI_printf (str : Interfaces.C.Strings.chars_ptr);
pragma Import (C, FCGI_printf, "FCGI_printf_wrapper");

Другая проблема программы заключается в том, что в Ada, в отличие от C и многих других языков, "\n" не является способом вставки символа новой строки в строку. Пытаться

fcgi_stdio.FCGI_printf
  (Interfaces.C.Strings.New_String ("Content-Type: text/plain" 
                                    & ASCII.LF & ASCII.LF));

[отредактировано 13.1.13]

person Simon Wright    schedule 12.01.2013
comment
Спасибо, поправил! Но ошибки все те же. - person user1091344; 13.01.2013
comment
Могу я спросить, как вы программируете на своем Mac? Как вы узнали, что он разбился на строке va_start (ap, format) ;? - person user1091344; 14.01.2013
comment
Я использую Emacs и обычно строю из командной строки. Я написал об этом в моем блоге. Кто-нибудь - что такое протокол SO? Стоит ли редактировать ответ здесь? - person Simon Wright; 14.01.2013