如何在 Go 中实现 DllMain 入口点
How to implement DllMain entry point in Go
我正在使用 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
方法。
我知道我可以 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 运行time,这不能在 DllMain
范围内完成(very few things 可以在 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()
我正在使用 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
方法。我知道我可以
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 运行time,这不能在 DllMain
范围内完成(very few things 可以在 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()