首页 > 解决方案 > 如何在 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 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() {
}

标签: pythonwindowsgodlldllmain

解决方案


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()

推荐阅读