当前位置: 首页 > 面试题库 >

Golang:调用Windows DLL函数

东方河
2023-03-14
问题内容

我正在编写一个调用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。

注意:如果您曾经用MinGW构建Boost,您可能还记得,Boost库的命名完全遵循上面链接中描述的模式。

过去在MinGW中存在直接链接到的问题.dll,因此建议创建一个静态库lib.a,.dll并从中导出符号并与其进行链接。现在,指向此MinGW Wiki页面的链接已失效,因此我认为直接针对.dll现在链接应该没问题。此外,我自己使用最新的MinGW-w64发行版做了几次,但还没有问题。

您需要链接标志,-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静态链接。



 类似资料:
  • 问题内容: 尝试从golang调用GetVolumeInformation函数。要获取卷名。 使用api的规范: 使用代码: …最后有错误:( 不理解,Google无法帮助调用winapi函数和returng字符串作为结果。 谢谢。 问题答案: 包裹不安全 不安全的软件包包含绕过Go程序的类型安全的操作。 类型指针 指针表示指向任意类型的指针。指针类型有四个特殊操作,而其他类型则不可用。 1)任何

  • Go 语言和 C 语言一样也有函数的概念,Go 语言中函数除了定义格式和不用声明以外,其它方面几乎和 C 语言一模一样,格式: func 函数名称(形参列表)(返回值列表){ 函数体; } 无参数无返回值函数 func say() { fmt.Println("Hello World!!!") } 有参数无返回值函数 func say(name string) { fmt

  • Go 语言中没有提供其它面向对象语言的析构函数,但是 Go 语言提供了 defer 语句用于实现其它面向对象语言析构函数的功能 defer 语句常用于 释放资源、解除锁定 以及 错误处理 等 例如C语言中我们申请了一块内存空间,那么不使用时我们就必须释放这块存储空间 例如C语言中我们打开了一个文件,那么我们不使用时就要关闭这个文件 例如C语言中我们打开了一个数据库, 那么我们不使用时就要关闭这个数

  • golang 里面有两个保留的函数: init 函数(能够应用于所有的 package) main 函数(只能应用于 package main) 这两个函数在定义时不能有任何的参数和返回值 go 程序会自动调用 init() 和 main(),所以你 不能 在任何地方调用这两个函数 package main 必须包含一个 main 函数,但是每个 package 中的 init 函数都是可选的 一

  • 问题内容: 我有一个类似于以下的代码 这不是实际的生产代码,但这是简化的版本。 问题:-如果取消注释该行,则会出现编译错误 如何执行通过Invoke()函数作为参数接收的函数? 什么是实现此目标的正确方法? 问题答案: 您可以使用的或方法将其作为函数调用。与所有方法一样,这种恐慌是错误的类型。 http://play.golang.org/p/xGmNLDcLL_

  • 匿名函数也是函数的一种,它的格式和普通函数一模一样,只不过没有名字而已 普通函数的函数名称是固定的, 匿名函数的函数名称是系统随机的 匿名函数可以定义在函数外(全局匿名函数),也可以定义在函数内(局部匿名函数),Go语言中的普通函数不能嵌套定义,但是可以通过匿名函数来实现函数的嵌套定义 全局匿名函数 package main import "fmt" // 方式一 var a = func(