Объедините C и TCL, используя Swig - PullRequest
1 голос
/ 21 сентября 2011

Я следовал руководству по объединению 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

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

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

Ответы [ 2 ]

1 голос
/ 22 сентября 2011

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

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

0 голосов
/ 03 апреля 2012

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

В 'ext.c':

#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);
%}
...