我正在编写一个调用Windows DLL的Go应用程序。该DLL是用MSVC编写的,并且使用__declspec(dllexport)具有外部“ C”导出。
我的Go应用程序的顶部如下:
//#cgo CFLAGS: -IC:/Repos/Module/include //#cgo LDFLAGS: -L. C:/Repos/Module/go/bin/MyModule.dll //#include <MyModule.h> import "C"
我从这样的模块中调用函数:
nRet := C.moduleImpl_len()
问题是,当我尝试运行此应用程序时,出现以下错误:
C:\Users\MINDO~1\AppData\Local\Temp\go-build836751819\mod\modimpl\_obj\modimpl.cgo2.o: In function `_cgo_e2aaf076ab69_Cfunc_moduleImpl_len': C:/Repos/Module/go/src/mod/modimpl/modimpl.go:90: undefined reference to `moduleImpl_len'
我用DUMPBIN查看了DLL导出的符号,它确切显示了“moduleImpl_len”作为导出的符号。这也是MyModule.h中定义的符号。
关于如何不必通过syscall路由即可获取符号链接的任何建议?
如果您尝试链接到DLL,则需要/想要LDFLAGS中的“-lMyModule”?
请看看ld和WIN32(cygwin / mingw)。特别是,直接链接到dll部分以获取有关-lLDWindows端口上标志行为的更多信息。提取:
例如,当使用参数-lxxx调用ld时,它将尝试在其搜索路径的第一个目录中查找,
libxxx.dll.a xxx.dll.a libxxx.a cygxxx.dll (*) libxxx.dll xxx.dll
移至搜索路径中的下一个目录之前。
(*)实际上不是,cygxxx.dll但实际上是<prefix>xxx.dll,<prefix>由ld选项设置-dll-search-prefix=<prefix>。对于cygwin,标准的gcc规范文件包括在内-dll-search-prefix=cyg,因此实际上我们实际上是在搜索cygxxx.dll。
(*)
<prefix>xxx.dll,<prefix>
-dll-search-prefix=<prefix>
-dll-search-prefix=cyg
注意:如果您曾经用MinGW构建Boost,您可能还记得,Boost库的命名完全遵循上面链接中描述的模式。
过去在MinGW中存在直接链接到的问题.dll,因此建议创建一个静态库lib.a,.dll并从中导出符号并与其进行链接。现在,指向此MinGW Wiki页面的链接已失效,因此我认为直接针对.dll现在链接应该没问题。此外,我自己使用最新的MinGW-w64发行版做了几次,但还没有问题。
您需要链接标志,-Wl,-Bstatic并且-Wl,-Bdynamic因为有时您想强制进行静态链接,例如,当搜索路径中也存在具有相同名称的动态库时:
-Wl,-Bstatic
-Wl,-Bdynamic
gcc object1.o object2.o -lMyLib2 -Wl,-Bstatic -lMyLib1 -Wl,-Bdynamic -o output
上面的代码段保证-l标记的默认链接优先级被覆盖MyLib1,即,即使MyLib1.dll搜索路径中存在,LD也会选择libMyLib1.a链接。请注意,对于MyLib2LD而言,它将再次偏向于动态版本。
注意:如果MyLib2依赖于MyLib1,那么MyLib1也会动态链接,无论如何-Wl,-Bstatic(即在这种情况下将其忽略)。为了防止这种情况,您也必须MyLib2静态链接。
MyLib2
MyLib1