python - 如何在 Go 中实现 DllMain 入口点
问题描述
我正在使用 Go 构建一个 DLL。
我无法实现 windows DllMain entry point。
我的目标是当应用程序通过LoadLibrary
调用该Test
方法加载 dll 时,DllMain
也将调用该方法。然而,目前该应用程序有点陷入僵局,没有任何反应。
该应用程序是非常简单的python代码
# App code
import ctypes
lib = ctypes.CDLL("./mydll.dll")
lib.Test()
笔记:
我正在使用
go version go1.16.4 windows/amd64
并使用
go build -o mydll.dll --buildmode=c-shared
如果我删除
DllMain
,一切正常,应用程序可以Test
成功调用该方法。我知道我可以指定
switch
条件DllMain
,例如附加进程、分离进程……等等,我只是想让它尽可能简单。
//Go Code
package main
import "C"
import (
"fmt"
"os"
)
//export Test
func Test() {
os.Create("fooFile")
}
//export DllMain
func DllMain(a uintptr, b uint32, c uintptr) int32 {
return 1
}
func main() {
}
解决方案
DllMain
不能是 Go 函数,因为第一次调用 Go 函数会初始化Go 运行时,这不能在范围内完成DllMain
(在范围内可以完成的事情很少)DllMain
。
作为一种解决方法,您可以DllMain
使用 C 编写并在单独的线程中调用 Go 代码,如本例所示。但是你不能与范围内的那个线程同步DllMain
,这样做会再次导致死锁。
也有_cgo_wait_runtime_init_done
,但它也是异步的。
因此,如果您需要在 DLL 附件上同步执行一些 Go 操作,那么您就不走运了。最好只定义一个“ Init
”导出函数并在调用任何其他 API 之前调用它。
当然,Go 中加载时初始化的惯用方式是通过init()
函数:
package main
import "C"
import (
"fmt"
)
func init() {
fmt.Println("init()")
}
//export Test
func Test() {
fmt.Println("Test()")
}
func main() {
}
编译并运行:
go build -o mydll.dll --buildmode=c-shared
rundll32 mydll,Test
输出:
init()
Test()
推荐阅读
- python - 将数据框中的一行复制到熊猫中的另一个数据框中的问题
- node.js - 使用 Sequelize 运行应用程序时如何处理数据库连接错误?
- java - Jhipster,弹簧,角罐工作,但不是战争工作
- asp.net-core - 发布到 .Net Core Web API 的最佳方式
- php - MYSQL比较日期时间不返回任何结果
- python - Python 如何处理 one-hot-encoded 数据?
- html - Ionic 4,带有中心按钮驼峰的选项卡菜单
- python - 有没有办法加快python中的重塑过程?
- react-native - 水平滚动视图不滚动?
- python - 在 Raspberry Pi 上使用 Python 从传感器存储数据的最有效方法