Gcc 获得;找不到符号。。。。在执行load时…“;尝试将Hello World作为C扩展名(dll)示例运行时出错
我使用了下面的C代码: 然后我创建了以下Tcl程序:Gcc 获得;找不到符号。。。。在执行load时…“;尝试将Hello World作为C扩展名(dll)示例运行时出错,gcc,dll,tcl,mingw,Gcc,Dll,Tcl,Mingw,我使用了下面的C代码: 然后我创建了以下Tcl程序: load hello.dll Hello puts "got here" 但在使用tclsh运行时,会出现以下错误: 找不到符号“Hello\u Init” 执行时 “加载。/hello.dll hello” (文件“hello.tcl”第1行) 因此,我基本上是在遵循Donal Fellows的一些建议。这里的答案是:然而,那里的OP评论说,和我一样,这些建议并没有解决他们的问题。有一件事我没有从这个答案中尝试,“你应该在你的库中有一个导
load hello.dll Hello
puts "got here"
但在使用tclsh运行时,会出现以下错误:
找不到符号“Hello\u Init”
执行时
“加载。/hello.dll hello”
(文件“hello.tcl”第1行)
因此,我基本上是在遵循Donal Fellows的一些建议。这里的答案是:然而,那里的OP评论说,和我一样,这些建议并没有解决他们的问题。有一件事我没有从这个答案中尝试,“你应该在你的库中有一个导出的(extern“C”)函数符号”——这可能是区别的制造者吗?这不应该一直都在这个例子中吗
根据comp.lang.tcl上某个人的建议,我找到了“DLL导出查看器”,但当我对DLL运行它时,它报告找到了0个函数:(我做错了什么
这可能是Windows上的MinGW/gcc的问题,我需要咬紧牙关,用Visual Studio来完成这项工作吗?如果可能的话,我希望避免这样做。问题的核心是,您的函数
Hello_Init
没有在结果DLL导出的全局符号表中结束。(一些链接器会将诸如\u Hello_Init
之类的东西放进中,而不是Hello_Init
;Tcl会透明地适应它们。)符号必须在那里,Tcl的加载
命令才能工作:没有它,就没有一致的方法告诉扩展代码Tcl_Interp
上下文句柄是什么(允许它生成命令、变量等)
(如果你一直在使用C++,可能的问题之一就是缺少<代码>外“C”<代码>,其实际意思是关闭名字的“Mangle”。这可能不是问题所在。
由于您在Windows上,使用DLL中的符号,例如EnterCriticalSection
和GetLastError
,问题可能与您的链接方式有关。我猜Tcl将您的函数定义为具有\uDeclSpec(dllexport)
(假设您尚未定义静态构建
,在构建DLL时绝对不应使用该定义)但这并没有得到尊重。假设您使用的是足够现代的GCC版本…您可能是。问题的核心是,您的函数Hello_Init
没有在结果DLL导出的全局符号表中结束。(一些链接器会将诸如\u Hello_Init
之类的东西放进中,而不是Hello_Init
;Tcl会透明地适应它们。)符号必须在那里,Tcl的加载
命令才能工作:没有它,就没有一致的方法告诉扩展代码Tcl_Interp
上下文句柄是什么(允许它生成命令、变量等)
(如果你一直在使用C++,可能的问题之一就是缺少<代码>外“C”<代码>,其实际意思是关闭名字的“Mangle”。这可能不是问题所在。
由于您在Windows上,使用DLL中的符号,例如EnterCriticalSection
和GetLastError
,问题可能与您的链接方式有关。我猜Tcl将您的函数定义为具有\uDeclSpec(dllexport)
(假设您尚未定义静态构建
,在构建DLL时绝对不应使用该定义)但这并没有得到尊重。假设您使用的是足够现代的GCC版本……您可能是。我也在经历如何在C中构建tcl扩展的过程,在使用tcl 8.6处理同一个示例时遇到了完全相同的问题
i、 e.我使用MinGW GCC(64位)进行编译,并使用了以下方法:
gcc -shared -o hello.dll -DUSE_TCL_STUBS "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\lib" -ltclstub86
和OP一样,我没有得到编译错误,但当在Tcsh提示符下加载dll时,tcl抱怨:
'找不到符号“Hello_Init”'
我不能说我理解,但由于一些尝试和错误,以及tcl wiki上的一些信息,我能够找到一个有效的解决方案
在我的例子中,我不得不将编译器语句调整为以下内容
gcc -shared -o hello.dll hello.c "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\bin" -ltcl86t
显然,这些文件路径是特定于我的系统的,但基本上
- 我必须添加对.c文件的显式引用
- 我必须从tcl-bin目录中包含
tcl86t
dll库
- 我必须删除
-DUSE\u TCL\u STUBS
标志(这意味着也可以删除引用-LC:\\ActiveTcl\\lib
和-ltclstub86
)
(试图使用-DUSE\u TCL\u STUBS
标志导致编译器向C:\ActiveTcl\lib/tclstub86.lib投诉:添加符号时出错:无法识别文件格式)
这成功地编译了一个我可以加载的dll,然后调用hello
函数来打印我的“helloworld”消息
我还绊倒了一件事,但这件事并不是很明显:
在阅读过程中,tcl会根据特定的命名约定执行查找“init”函数。
如果C扩展没有定义包名,那么初始化函数的名称将从dll文件名派生。
这给我带来了一些问题(当通过EclipseIDE编译时),因为dll名称是根据EclipseProjet名称自动确定的
例如,如果我重新编译同一个示例,但是调用.dll,例如
gcc -shared -o helloWorldExenstion.dll hello.c "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\bin" -ltcl86t
然后在tclsh提示下:
% load helloWorldExtension
cannot find symbol "Helloworldextension_Init"
我还经历了如何用C构建tcl扩展的过程,在使用TCL8.6处理同一个示例时遇到了完全相同的问题
i、 e.我使用MinGW GCC(64位)进行编译,并使用了以下方法:
gcc -shared -o hello.dll -DUSE_TCL_STUBS "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\lib" -ltclstub86
和OP一样,我没有得到编译错误,但当在Tcsh提示符下加载dll时,tcl抱怨:
'找不到符号“Hello_Init”'
<
% load helloWorldExtension
cannot find symbol "Helloworldextension_Init"