Gcc 获得;找不到符号。。。。在执行load时…“;尝试将Hello World作为C扩展名(dll)示例运行时出错

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评论说,和我一样,这些建议并没有解决他们的问题。有一件事我没有从这个答案中尝试,“你应该在你的库中有一个导

我使用了下面的C代码:

然后我创建了以下Tcl程序:

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"