Golang中处理DLL的_stdcall函数和LPSTR变量的方法

Golang中处理DLL的_stdcall函数和LPSTR变量的方法 你好!

我正在尝试创建一个与VB6兼容的DLL(使用 // +build windows win32),在函数中使用 _stdcall,在变量中使用 LPSTR
我在网上搜索了,但找不到解决方案。

谢谢

4 回复

我该如何使用gccgo进行尝试?在哪里可以下载它?

更多关于Golang中处理DLL的_stdcall函数和LPSTR变量的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


https://golang.org/doc/install/gccgo

提示:请使用谷歌搜索。

我可能完全理解错了,先道个歉,但我认为GC(Go编译器)就是不兼容的。你可以使用cgo进行FFI调用。

要实现你的需求,应该尝试用gccgo进行编译。

在Go中调用使用_stdcall调用约定的DLL函数并处理LPSTR参数,需要使用syscall包和syscall.NewLazyDLL。以下是具体实现方法:

// +build windows

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

// 定义函数原型
var (
    dll                 = syscall.NewLazyDLL("your_dll_name.dll")
    yourFunction        = dll.NewProc("YourFunctionName")
)

// 对于使用_stdcall调用约定的函数
func CallStdCallFunction(param1 uintptr, param2 uintptr) (uintptr, error) {
    ret, _, err := yourFunction.Call(param1, param2)
    if err != syscall.Errno(0) {
        return 0, err
    }
    return ret, nil
}

// 处理LPSTR参数
func CallWithLPSTR() {
    // 将Go字符串转换为LPSTR
    str := "Hello from Go"
    lpstr := syscall.StringToUTF16Ptr(str)
    
    // 调用函数
    ret, err := CallStdCallFunction(uintptr(unsafe.Pointer(lpstr)), 0)
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
    fmt.Printf("Return value: %d\n", ret)
}

// 如果DLL函数返回LPSTR
func GetLPSTRFromDLL() string {
    var yourFunctionGetString = dll.NewProc("GetStringFunction")
    
    ret, _, _ := yourFunctionGetString.Call()
    
    // 将返回的LPSTR转换为Go字符串
    str := syscall.UTF16PtrToString((*uint16)(unsafe.Pointer(ret)))
    return str
}

func main() {
    CallWithLPSTR()
    result := GetLPSTRFromDLL()
    fmt.Printf("Received string: %s\n", result)
}

对于需要导出的函数(供VB6调用),可以使用//export指令和C包:

// +build windows

package main

/*
#include <windows.h>
*/
import "C"
import (
    "unsafe"
)

//export YourGoFunction
func YourGoFunction(lpstr *C.char) C.int {
    // 将C的char*转换为Go字符串
    goStr := C.GoString(lpstr)
    
    // 处理逻辑
    println("Received:", goStr)
    
    return 0
}

func main() {
    // 保持程序运行
    select {}
}

编译时需要指定构建标签:

go build -tags windows

注意:

  1. syscall.Call自动处理_stdcall调用约定
  2. syscall.StringToUTF16Ptr将Go字符串转换为Windows LPSTR
  3. unsafe.Pointer用于指针类型转换
  4. 返回的LPSTR需要使用syscall.UTF16PtrToString转换回Go字符串
回到顶部