1

我正在使用 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() {
}
4

1 回答 1

2

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()
于 2021-06-14T12:33:36.837 回答