wails
wails copied to clipboard
启用CGO 之后功能不正常
Description
我启用cgo打包用到的命令 $env:CGO_ENABLED="1";wails build -platform windows/amd64 -clean -o daliTools.exe 这种情况下,打包完成dll没有复制到bin目录下,我手动复制dll到bin目录下,虽然log.Fatal没有报错 同样代码什么都没有改动 ,打包命令仅仅加个-debug ,程序就正常了,能正常访问dll里面的接口,也有信息返回,但是去掉-debug就不行了,是不是正常打包去掉了什么正是我需要的
To Reproduce
1.启用cgo 2.loadDll 3.调用里面的方法
Expected behaviour
dll方法里面返回信息
Screenshots
dll, err := syscall.LoadDLL("Knx.Sdk.dll")
if err != nil {
log.Fatal("DLL 加载失败:", err)
return
}
sdkDll = dll
// 获取创建隔离线程函数
createIsolate, err := dll.FindProc("graal_create_isolate")
if err != nil {
fmt.Printf("查找 graal_create_isolate 函数失败: %v\n", err)
return
}
// 创建参数结构体
params := &GraalCreateIsolateParams{
Version: 4, // 当前版本为4
}
// 创建指针用于接收结果
var isolate *GraalIsolate
// 调用创建隔离线程函数
ret, _, err := createIsolate.Call(
uintptr(unsafe.Pointer(params)),
uintptr(unsafe.Pointer(&isolate)),
uintptr(unsafe.Pointer(&thread)),
)
if ret != 0 {
fmt.Printf("创建隔离线程失败: %v\n", err)
return
}
fmt.Printf("隔离线程创建成功\n")
}
### Attempted Fixes
_No response_
### System Details
```shell
# Wails
Version | v2.10.1
# System
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
| OS | Windows 10 Pro |
| Version | 2009 (Build: 26100) |
| ID | 24H2 |
| Go Version | go1.24.1 |
| Platform | windows |
| Architecture | amd64 |
| CPU | Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz |
| GPU 1 | OrayIddDriver Device (Shanghai Best Oray Information Technology Co., Ltd.) - Driver: 17.1.58.818 |
| GPU 2 | Intel(R) HD Graphics 630 (Intel Corporation) - Driver: 24.20.100.6287 |
| GPU 3 | NVIDIA GeForce GTX 1050 Ti with Max-Q Design (NVIDIA) - Driver: 22.21.13.8554 |
| Memory | 32GB |
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
# Dependencies
┌───────────────────────────────────────────────────────┐
| Dependency | Package Name | Status | Version |
| WebView2 | N/A | Installed | 136.0.3240.92 |
| Nodejs | N/A | Installed | 22.14.0 |
| npm | N/A | Installed | 10.9.2 |
| *upx | N/A | Available | |
| *nsis | N/A | Available | |
| |
└─────────────── * - Optional Dependency ───────────────┘
# Diagnosis
Optional package(s) installation details:
- upx : Available at https://upx.github.io/
- nsis : More info at https://wails.io/docs/guides/windows-installer/
Additional context
No response
👋 Thanks for reporting this issue! To help us investigate, could you please:
- Add the output of
wails doctorif not already included - Provide clear steps to reproduce the issue
- If possible, create a minimal reproduction of the issue
This will help us resolve your issue much faster. Thank you!
👋 Thanks for reporting this issue! To help us investigate, could you please:
- Add the output of
wails doctorif not already included - Provide clear steps to reproduce the issue
- If possible, create a minimal reproduction of the issue
This will help us resolve your issue much faster. Thank you!
通过一步步写文件测试发现是fmt.Printf("调用 SearchKnxServers 函数失败: %v\n", err1)报错了,报的错误信息为The handle is invalid. 能帮我看下是哪方面的问题吗?
/*
#include <stdlib.h>
*/
import "C"
import (
"errors"
"fmt"
"log"
"syscall"
"unsafe"
)
// GraalIsolate 定义隔离线程相关结构体
type GraalIsolate struct{}
type GraalIsolateThread struct{}
// GraalCreateIsolateParams 创建隔离线程的参数结构体
type GraalCreateIsolateParams struct {
Version int32 // 结构体版本
ReservedAddressSpaceSize uintptr // 保留地址空间大小
AuxiliaryImagePath *byte // 辅助镜像路径
AuxiliaryImageReservedSpaceSize uintptr // 辅助镜像保留空间大小
Reserved1 int32 // 内部使用
Reserved2 **byte // 内部使用
Pkey int32 // 隔离保护键或域
Reserved3 byte // 内部使用
Reserved4 byte // 内部使用
}
var sdkDll *syscall.DLL
var searchKnxServersProc *syscall.Proc
var thread *GraalIsolateThread
func DestoryDll() {
sdkDll.Release()
}
func InitSdkDll() {
dll, err := syscall.LoadDLL("Knx.Sdk.dll")
if err != nil {
log.Fatal("DLL 加载失败:", err)
return
}
sdkDll = dll
// 获取创建隔离线程函数
createIsolate, err := dll.FindProc("graal_create_isolate")
if err != nil {
fmt.Printf("查找 graal_create_isolate 函数失败: %v\n", err)
return
}
// 创建参数结构体
params := &GraalCreateIsolateParams{
Version: 4, // 当前版本为4
}
// 创建指针用于接收结果
var isolate *GraalIsolate
// 调用创建隔离线程函数
ret, _, err := createIsolate.Call(
uintptr(unsafe.Pointer(params)),
uintptr(unsafe.Pointer(&isolate)),
uintptr(unsafe.Pointer(&thread)),
)
if ret != 0 {
fmt.Printf("创建隔离线程失败: %v\n", err)
return
}
fmt.Printf("隔离线程创建成功\n")
}
func SearchServers() (string, error) {
if searchKnxServersProc == nil {
proc, err := sdkDll.FindProc("SearchKnxServers")
if err != nil {
fmt.Printf("查找 SearchKnxServers 函数失败: %v\n", err)
return "", err
}
searchKnxServersProc = proc
}
// 调用函数获取结果
result, _, err1 := searchKnxServersProc.Call(uintptr(unsafe.Pointer(thread)))
if !errors.Is(err1, syscall.Errno(0)) {
fmt.Printf("调用 SearchKnxServers 函数失败: %v\n", err1)
return "", err1
}
// 将结果转换为 Go 字符串
jsonStr := C.GoString((*C.char)(unsafe.Pointer(result)))
return jsonStr, nil
}
InitSdkDll 里面不会报错 ,也能获取到SearchKnxServers 返回的信息, 调用完InitSdkDll 再SearchServers里面就会报错,但是wails dev 和打包的时候加上-debug命令又正常了
/*
#include <stdlib.h>
*/
import "C"
import (
"errors"
"fmt"
"log"
"os"
"syscall"
"unsafe"
)
// GraalIsolate 定义隔离线程相关结构体
type GraalIsolate struct{}
type GraalIsolateThread struct{}
// GraalCreateIsolateParams 创建隔离线程的参数结构体
type GraalCreateIsolateParams struct {
Version int32 // 结构体版本
ReservedAddressSpaceSize uintptr // 保留地址空间大小
AuxiliaryImagePath *byte // 辅助镜像路径
AuxiliaryImageReservedSpaceSize uintptr // 辅助镜像保留空间大小
Reserved1 int32 // 内部使用
Reserved2 **byte // 内部使用
Pkey int32 // 隔离保护键或域
Reserved3 byte // 内部使用
Reserved4 byte // 内部使用
}
var sdkDll *syscall.DLL
var searchKnxServersProc *syscall.Proc
var thread *GraalIsolateThread
func DestoryDll() {
sdkDll.Release()
}
func InitSdkDll() {
dll, err := syscall.LoadDLL("Knx.Sdk.dll")
if err != nil {
log.Fatal("DLL 加载失败:", err)
return
}
sdkDll = dll
// 获取创建隔离线程函数
createIsolate, err := dll.FindProc("graal_create_isolate")
if err != nil {
fmt.Printf("查找 graal_create_isolate 函数失败: %v\n", err)
return
}
// 创建参数结构体
params := &GraalCreateIsolateParams{
Version: 4, // 当前版本为4
}
// 创建指针用于接收结果
var isolate *GraalIsolate
// 调用创建隔离线程函数
ret, _, err := createIsolate.Call(
uintptr(unsafe.Pointer(params)),
uintptr(unsafe.Pointer(&isolate)),
uintptr(unsafe.Pointer(&thread)),
)
if ret != 0 {
fmt.Printf("创建隔离线程失败: %v\n", err)
return
}
fmt.Printf("隔离线程创建成功\n")
proc, err := sdkDll.FindProc("SearchKnxServers")
if err != nil {
data1 := "查找 SearchKnxServers 函数失败"
_ = os.WriteFile("output.txt", []byte(data1), 0644)
fmt.Printf("查找 SearchKnxServers 函数失败: %v\n", err)
}
// 调用函数获取结果
result, _, err1 := proc.Call(uintptr(unsafe.Pointer(thread)))
if !errors.Is(err1, syscall.Errno(0)) {
data2 := "调用 SearchKnxServers 函数失败" + err1.Error()
_ = os.WriteFile("output.txt", []byte(data2), 0644)
fmt.Printf("调用 SearchKnxServers 函数失败: %v\n", err1)
}
// 将结果转换为 Go 字符串
jsonStr := C.GoString((*C.char)(unsafe.Pointer(result)))
data3 := "调用 SearchKnxServers 函数返回信息:" + jsonStr
_ = os.WriteFile("output.txt", []byte(data3), 0644)
}
func SearchServers() (string, error) {
proc, err := sdkDll.FindProc("SearchKnxServers")
if err != nil {
fmt.Printf("查找 SearchKnxServers 函数失败: %v\n", err)
return "", err
}
// 调用函数获取结果
result, _, err1 := proc.Call(uintptr(unsafe.Pointer(thread)))
if !errors.Is(err1, syscall.Errno(0)) {
fmt.Printf("调用 SearchKnxServers 函数失败: %v\n", err1)
return "", err1
}
// 将结果转换为 Go 字符串
jsonStr := C.GoString((*C.char)(unsafe.Pointer(result)))
return jsonStr, nil
}
经过测试下来,如果打成正式包 就不能把*syscall.DLL单独提取出来,存到内存中,不然就报错需要打成debug包 var sdkDll *syscall.DLL var searchKnxServersProc *syscall.Proc var thread *GraalIsolateThread
经过测试,应该不是wails的问题,但我不知道怎么解决
我测试手动构建,我只要加上-H windowsgui,就不行了,应该是GRAAL VM编译出来的DLL依赖于黑窗口
go build -tags desktop,production -gcflags "all=-N -l" -ldflags "-H windowsgui"