Объедините C и TCL, используя Swig

Я следил за учебным пособием по объединению C с TCL с использованием Swig. Учебник, казалось, работал правильно, но в конце я столкнулся с ошибкой, которую не могу решить. Ситуация следующая:

Я следил за учебником: http://www.swig.org/tutorial.html.

У меня есть файл с именем test.c:

char *HelloWorld()
{
    return "hello world";
}

и еще один с именем test.i:

%module test
%{
/* Put header files here or function declarations like below */
extern char *HelloWorld();
%}

extern char *HelloWorld();

Затем я использовал следующие аргументы командной строки для подготовки правильных файлов:

gcc -c test.c -o test.o
swig -tcl test.i 
gcc -c test_wrap.c -o test_wrap.o
gcc -dynamiclib -framework Tcl  test.o test_wrap.o -o test.so

И, наконец, я попытался загрузить его, используя:

tclsh
% load test.so test

Это тот момент, когда я получил следующую ошибку:

dlsym(0x100600090, Test_Unload): symbol not founddlsym(0x100600090, Test_SafeUnload): symbol not found

Насколько я знаю, я не отклонялся от учебника. Может ли кто-нибудь сказать мне, как я получил эту ошибку и, что более важно, как избавиться от нее?

Заранее спасибо!


person Tom    schedule 21.09.2011    source источник
comment
Tcl имеет собственный отличный интерфейс для кода C. Я бы рекомендовал просто изучить его, а не тратить время на SWIG.   -  person kostix    schedule 21.09.2011
comment
Я бы хотел, но причина, по которой я делаю это руководство, заключается в том, что я могу позже использовать уже предоставленный интерфейс SWIG и файл C в своих сценариях TCL. Боюсь, это не сработает с другими способами использования кода C в TCL.   -  person Tom    schedule 21.09.2011
comment
выполните «file test.so» и «nm -AC test.so» и покажите вывод   -  person vrdhn    schedule 19.02.2012


Ответы (2)


Эти сообщения об ошибках мешают работе load? Они не должны; они сообщают, что низкоуровневый API для поддержки выгрузки расширения отсутствует, но это нормально (многие расширения невозможно выгрузить; сложно написать код, поддерживающий это).

Вы не указываете, какую именно версию Tcl вы используете, но она должна быть не ниже 8.5, чтобы эти символы можно было даже искать в первую очередь, поэтому немного сложно догадаться, в чем именно заключается проблема. (О сообщении просто не следует сообщать.) Я советую подать отчет об ошибке. на этом; убедитесь, что вы включили в отчет все точные версии.

person Donal Fellows    schedule 22.09.2011

Я давно не использовал SWIG, поэтому я не уверен, дает ли он достаточный контроль над генерируемым им кодом, чтобы вы могли применить это исправление. Замалчивая эту деталь, я могу воспроизвести (и исправить) проблему следующим образом:

В «доп.с»:

#include <tcl.h>

int DLLEXPORT Ext_Init(Tcl_Interp *interp) {


    if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
        return TCL_ERROR;
    }
    if (Tcl_PkgProvide(interp, "Ext", "0.0") == TCL_ERROR) {
        return TCL_ERROR;
    }

    return TCL_OK;
}

Собираем, запускаем tclsh, загружаем расширение:

$ gcc -dynamiclib -framework Tcl ext.c -o ext.so
$ tclsh8.5
% load ./ext.so
dlsym(0x400000, Ext_SafeInit): symbol not found
dlsym(0x400000, Ext_Unload): symbol not found
dlsym(0x400000, Ext_SafeUnload): symbol not found

Что-то внутреннее в коде загрузки библиотеки помещает это сообщение об ошибке в результат интерпретатора. Чтобы остановить появление сообщения, установите или сбросьте результат, чтобы функция _Init() заканчивалась одним или другим из:

//    Set the result to a message of your choosing
    Tcl_SetObjResult(interp, Tcl_NewStringObj("ok", -1));

//    Or clear out the result altogether
    Tcl_ResetResult(interp);
    return TCL_OK;
}

блок инициализации в swig может вставить код в нужное место, чтобы добиться того же результата:

%init %{
Tcl_ResetResult(interp);
%}
person Chris    schedule 03.04.2012