使用Swig组合C和TCL
我一直在学习如何使用Swig将C与TCL结合起来的教程。教程似乎运行正常,但最后我遇到了一个无法解决的错误。情况如下: 我下面的教程是: 我有一个名为test.c的文件:使用Swig组合C和TCL,c,tcl,swig,dlsym,C,Tcl,Swig,Dlsym,我一直在学习如何使用Swig将C与TCL结合起来的教程。教程似乎运行正常,但最后我遇到了一个无法解决的错误。情况如下: 我下面的教程是: 我有一个名为test.c的文件: char *HelloWorld() { return "hello world"; } 和另一个命名测试。i: %module test %{ /* Put header files here or function declarations like below */ extern char *HelloWor
char *HelloWorld()
{
return "hello world";
}
和另一个命名测试。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
据我所知,我没有偏离教程。有谁能告诉我,我是如何得到这个错误的,更重要的是,如何摆脱它
提前谢谢 这些错误消息是否停止了
加载
的工作?他们不应该;他们报告说,支持卸载扩展的低级API不存在,但这没关系(很多扩展无法卸载;编写支持它的代码很棘手)
你没有提到你使用的是哪一个版本的Tcl,但它必须至少是8.5,才能在第一时间搜索到这些符号,所以很难猜测到底是什么问题。(该信息不应被报道。)我建议就此提交一份报告;确保在报告中包含所有准确版本。这些错误消息是否会停止加载?他们不应该;他们报告说,支持卸载扩展的低级API不存在,但这没关系(很多扩展无法卸载;编写支持它的代码很棘手)
你没有提到你使用的是哪一个版本的Tcl,但它必须至少是8.5,才能在第一时间搜索到这些符号,所以很难猜测到底是什么问题。(该信息不应被报道。)我建议就此提交一份报告;请确保在报告中包含所有准确的版本。我使用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;
}
库加载代码的内部内容是将错误消息放入解释器结果中。要停止出现消息,请设置或重置结果,以便_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);
%}
我已经很久没有使用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;
}
库加载代码的内部内容是将错误消息放入解释器结果中。要停止出现消息,请设置或重置结果,以便_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);
%}
Tcl有自己优秀的C代码接口。我建议大家学习一下,而不要在SWIG上浪费时间。我会的,但我之所以要学习本教程,是为了以后可以在我的TCL脚本中使用已经提供的SWIG接口和C文件。我担心它无法与其他在TCL中使用C代码的方法一起使用。请执行“file test.so”和“nm-AC test.so”并显示OutputCL有自己优秀的C代码接口。我建议大家学习一下,而不要在SWIG上浪费时间。我会的,但我之所以要学习本教程,是为了以后可以在我的TCL脚本中使用已经提供的SWIG接口和C文件。恐怕它无法与其他在TCL中使用C代码的方法一起使用。请执行“file test.so”和“nm-AC test.so”并显示输出