【问题标题】:Combine C and TCL using Swig使用 Swig 结合 C 和 TCL
【发布时间】:2011-09-21 09:48:17
【问题描述】:

我一直在关注使用 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

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

提前致谢!

【问题讨论】:

  • Tcl 有自己的优秀 C 代码接口。我建议只研究它,而不是在 SWIG 上浪费时间。
  • 我会,但我做这个教程的原因是我以后可以在我的 TCL 脚本中使用已经提供的 SWIG 接口和 C 文件。恐怕它不适用于在 TCL 中使用 C 代码的其他方式。
  • 执行 'file test.so' 和 'nm -AC test.so' 并显示输出

标签: c tcl swig dlsym


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    %init %{
    Tcl_ResetResult(interp);
    %}
    

    【讨论】:

      猜你喜欢
      • 2013-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多