如何在Go和Swig中使用LPCWSTR?

我正在尝试使用带有Go的C库使用Swig.这是简化的代码,我知道我可以使用cgo,但我需要使用带有Swig的LPCWSTR参数的函数.

我在https://github.com/AllenDang/w32/blob/c92a5d7c8fed59d96a94905c1a4070fdb79478c9/typedef.go上看到LPCWSTR相当于* uint16所以syscall.UTF16PtrFromString()似乎是我需要的,但是当我运行代码时出现异常.

我想知道我是否应该使用SwigcptrLPCWSTR.

libtest.c

#include <windows.h>
#include <stdio.h>

#include "libtest.h"

__stdcall void hello(const LPCWSTR s)
{
    printf("hello: %ls\n", s);
}

libtest.h

#ifndef EXAMPLE_DLL_H
#define EXAMPLE_DLL_H

#include <windows.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifdef BUILDING_EXAMPLE_DLL
#define EXAMPLE_DLL __declspec(dllexport)
#else
#define EXAMPLE_DLL __declspec(dllimport)
#endif

void __stdcall EXAMPLE_DLL hello(const LPCWSTR s);

#ifdef __cplusplus
}
#endif

#endif

我使用以下命令构建lib和DLL:

gcc -c -DBUILDING_EXAMPLE_DLL libtest.c
gcc -shared -o libtest.dll libtest.o -Wl,--out-implib,libtest.a

main.swig

%module main

%{
#include "libtest.h"
%}

%include "windows.i"
%include "libtest.h"

main.go

package main

import (
    "syscall"
    "unsafe"
)

func main() {
    p, err := syscall.UTF16PtrFromString("test")
    if err != nil {
        panic(err)
    }
    Hello(SwigcptrLPCWSTR(unsafe.Pointer(p)))
}

跟踪

Exception 0xc0000005 0x0 0xffffffffffffffff 0x7ffcc761f2e1
PC=0x7ffcc761f2e1
signal arrived during external code execution

main._Cfunc__wrap_hello_main_90cec49f7d68ac58(0xc082002110)
        _/D_/lpcwstr/go/_obj/_cgo_gotypes.go:53 +0x38
main.Hello(0x500028, 0xc082002120)
        _/D_/lpcwstr/go/_obj/main.go:63 +0x3c
main.main()
        D:/lpcwstr/go/main.go:9 +0x96

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
        c:/go/src/runtime/asm_amd64.s:1696 +0x1
rax     0x6c007400690074
rbx     0x6c007400690074
rcx     0x7ffffffe
rdi     0x24fd73
rsi     0x7
rbp     0x24fb00
rsp     0x24fa00
r8      0xffffffffffffffff
r9      0x7ffcc75d0000
r10     0x0
r11     0x200
r12     0xffffffff
r13     0x24fd60
r14     0x10
r15     0x6264403a
rip     0x7ffcc761f2e1
rflags  0x10202
cs      0x33
fs      0x53
gs      0x2b

最佳答案 我怀疑你看到的问题是因为你传入SWIG的是一个双指针而不仅仅是一个指针,即wchar_t **而不仅仅是wchar_t *.

我认为这是因为您调用UTF16PtrFromString,它接受UTF16字符串的地址,然后调用unsafe.Pointer(p),我认为再次获取其输入的地址.

从go源代码:

func UTF16PtrFromString(s string) (*uint16) {
    a := UTF16FromString(s)
    return &a[0]
}

所以我想如果你反而使用:

func main() {
    p, err := syscall.UTF16FromString("test") // Note the subtle change here
    if err != nil {
        panic(err)
    }
    Hello(SwigcptrLPCWSTR(unsafe.Pointer(p)))
}

它应该按预期工作.

点赞