1

我一直在关注使用 Swig 将 C 与 TCL 结合起来的教程。该教程似乎工作正常,但最后我遇到了一个我无法解决的错误。情况如下:

我关注的教程是: 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

据我所知,我没有偏离教程。谁能告诉我我是怎么得到这个错误的,更重要的是如何摆脱它?

提前致谢!

4

2 回答 2

1

这些错误消息是否会阻止load工作?他们不应该;他们报告说不存在支持卸载扩展的低级 API,但没关系(很多扩展无法卸载;编写支持它的代码很棘手)。

您没有确切提及您使用的是哪个版本的 Tcl — 但首先要搜索这些符号必须至少为 8.5 — 因此很难猜测确切的潜在问题是什么。(根本不应该报告该消息。)我建议对此提交错误报告确保在报告中包含所有准确版本。

于 2011-09-22T08:24:57.477 回答
0

自从我使用 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 块功能可能会在正确的位置插入代码来实现相同的目的:

%init %{
Tcl_ResetResult(interp);
%}
于 2012-04-03T14:50:07.230 回答