【问题标题】:How to implement DllMain entry point in Go如何在 Go 中实现 DllMain 入口点
【发布时间】:2021-08-30 07:25:53
【问题描述】:

我正在使用 Go 构建一个 DLL。

我无法实现 windows DllMain entry point

我的目标是当应用程序通过LoadLibrary 加载dll 以调用Test 方法时,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 方法。

  • 我知道我可以在DllMain 下使用switch 来指定诸如进程附加、分离等条件,我只是想让它尽可能简单。

//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() {
}

【问题讨论】:

    标签: python windows go dll dllmain


    【解决方案1】:

    DllMain 不能是 Go 函数,因为第一次调用 Go 函数会初始化 Go 运行时,这不能在 DllMain 范围内完成(有 @ 987654321@,可以在DllMain的范围内完成)。

    作为一种解决方法,您可以在 C 中编写 DllMain 并在 单独的线程 中调用 Go 代码,就像在 this example 中一样。但是你不能和DllMain范围内的那个线程同步,这样做又会导致死锁。

    还有_cgo_wait_runtime_init_done,但也是异步的。

    因此,如果您需要在 DLL 附件上同步执行一些 Go 操作,那么您就不走运了。最好只定义一个“Init”导出函数并在调用任何其他 API 之前调用它。

    当然,Go 中加载时初始化的惯用方式是通过 init() function:

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

    【讨论】:

      猜你喜欢
      • 2016-12-30
      • 2018-04-16
      • 2016-05-08
      • 1970-01-01
      • 1970-01-01
      • 2021-12-14
      • 1970-01-01
      • 1970-01-01
      • 2011-03-03
      相关资源
      最近更新 更多