CGo 将 go 字符串转换为 *C.uchar

CGo Convert go string to *C.uchar

var originalMsg *C.uchar
C.ecall_pay_w(8, 10, &originalMsg, &signature)
originalMsgStr := fmt.Sprintf("%c", originalMsg)

//Todo convert originalMstStr to same value with originalMsg

我必须将 go str(original MsgStr) 转换为 *C.uchar 类型,这与原始 Message 的值相同。 我该怎么做?

我不太了解 Go,但不要忘记在 C 中 *C.uchar 类似于 unsigned char *,它通常用于引用字符串(以 Null 结尾的数组个字符)。

在这里您使用 fmt.Sprintf("%c", originalMsg),而 %c 需要一个字符,所以除了关于如何 cast 结果字符串的语言细节对于 *C.uchar,您很可能已经丢失了 content

%c the character represented by the corresponding Unicode code point

来自https://golang.org/pkg/fmt/#hdr-Printing

您从对 C.ecall_pay_w 的调用中获得了一个 C 字符串,并希望将该 C 字符串转换为 Go 字符串。您可以通过手动跟随 C 字符串直到到达终止 0.

来执行此操作

假设:

  • C-string
  • 末尾有终止符0
  • C 字符串被编码为 ASCII,因此每个字节代表一个 ASCII 字符(在 [0..127] 范围内)。这意味着它同时是 ASCII 和 UTF-8,因为 UTF-8 向后兼容 ASCII。

那么你的解决方案可能是这样的:

    func convertCStringToGoString(c *C.uchar) string {
        var buf []byte
        for *c != 0 {
            buf = append(buf, *c)
            c = (*C.uchar)(unsafe.Pointer(uintptr(unsafe.Pointer(c)) + 1))
        }
        return string(buf)
    }

请注意,在 Go 中做 "unsafe" 这样的事情是大量的。这是 Go 作者故意完成的。您需要先转换为 unsafe.Pointer,然后才能转换为 uintptruintptr 可以添加到 (+ 1) 而 unsafe.Pointer 不支持。这些就是这么多铸造的原因。