英文:
How do I properly convert a UTF-8 encoded char array to a Go string when using a C-library in Go?
问题
我正在尝试在Go语言中使用一个C库。C.PrlFoundVmInfo_GetName
函数将一个UTF-8编码的字符串写入name中,长度为nBufSize。
以下是正确声明name(和nBufSize)并将name转换为Go语言字符串的方法。上面的代码不按照我期望的方式工作。它打印出:
VM 1024 name: ""
C API文档,摘录
PrlFoundVmInfo_GetName - 参数
PRL_RESULT PrlFoundVmInfo_GetName(
PRL_HANDLE handle,
PRL_STR sName,
PRL_UINT32_PTR pnNameBufLength
);
- handle - 类型为PHT_FOUND_VM_INFO的句柄,用于标识容器。
- sName - [输出] 用于接收名称的缓冲区的指针。传递一个空指针以确定所需的缓冲区大小。
- pnNameBufLength - [输入] 用于接收输出数据的缓冲区的大小(以字节为单位)。[输出] 如果缓冲区参数包含空指针或指定的缓冲区大小不够大,则为所需的缓冲区大小。
完整的文档可在C API文档 - PrlFoundVmInfo_GetName中找到。
英文:
I'm trying to use a C library in Go. The C.PrlFoundVmInfo_GetName
function writes a UTF-8 encoded string into name with length nBufSize.
<!-- language: lang-go -->
// PRL_CHAR sName[1024];
var sName [1024]C.PRL_CHAR
// PRL_UINT32 nBufSize = sizeof(sName);
var nBufSize C.PRL_UINT32 = C.PRL_UINT32(unsafe.Sizeof(sName))
ret = C.PrlFoundVmInfo_GetName(hFoundVmInfo, (*C.PRL_CHAR)(unsafe.Pointer(&sName)), &nBufSize)
// printf("VM name: %s\n", sName);
var gName string = C.GoString((*C.char)(unsafe.Pointer(&sName)))
fmt.Printf("VM %d name: \"%s\"\n", nBufSize, gName)
What is the proper way to declare name (and nBufSize) and how do i convert name to a Go string? The above code dosen't work as I expect. It prints:
VM 1024 name: ""
...
C API Documentation, extract
PrlFoundVmInfo_GetName - Parameters
<!-- language: lang-c -->
PRL_RESULT PrlFoundVmInfo_GetName(
PRL_HANDLE handle,
PRL_STR sName,
PRL_UINT32_PTR pnNameBufLength
);
- handle - A handle of type PHT_FOUND_VM_INFO identifying the container.
- sName - [out] A pointer to a buffer that receives the name. Pass a null pointer to determine the required buffer size.
- pnNameBufLength - [in] The size of the buffer used to receive the output data (in bytes). [out] The required buffer size if the buffer parameter contains a null pointer or if the specified buffer size is not large enough.
The full documentation is available at C API Documentation - PrlFoundVmInfo_GetName
答案1
得分: 3
> 命令 cgo
>
> Go 对 C 的引用
>
> 一些特殊的函数通过复制数据来在 Go 和 C 类型之间进行转换。在伪代码中定义如下:
>
> // C 字符串,长度转为 Go 字符串
> func C.GoStringN(*C.char, C.int) string
英文:
> Command cgo
>
> Go references to C
>
> A few special functions convert between Go and C types by making
> copies of the data. In pseudo-Go definitions:
>
> // C string, length to Go string
> func C.GoStringN(*C.char, C.int) string
答案2
得分: 0
这是解决方案,创建一个字节数组并使 sName 指向它。在使用后,使用 C.GoStringN
将内容转换为 Go 字符串。
var buf = make([]byte, 1024)
var sName C.PRL_STR = (C.PRL_STR)(unsafe.Pointer(&buf))
var nBufSize C.PRL_UINT32 = 1024
ret = C.PrlFoundVmInfo_GetName(*hFoundVmInfo, sName, &nBufSize)
gName := C.GoStringN((*_Ctype_char)(unsafe.Pointer(sName)), C.int(nBufSize))
fmt.Printf("VM %d name: \"%s\"\n", nBufSize, gName)
英文:
This was the solution, create a byte array and make sName point to it. When it has been used use C.GoStringN
to convert the content to a Go string.
<!-- language: lang-go -->
var buf = make([]byte, 1024)
var sName C.PRL_STR = (C.PRL_STR)(unsafe.Pointer(&buf))
var nBufSize C.PRL_UINT32 = 1024
ret = C.PrlFoundVmInfo_GetName(*hFoundVmInfo, sName, &nBufSize)
gName := C.GoStringN((*_Ctype_char)(unsafe.Pointer(sName)), C.int(nBufSize))
fmt.Printf("VM %d name: \"%s\"\n", nBufSize, gName)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论