在 C 函数中更改 golang C.String 变量的值

Change value of golang C.String variable in C function

我想从 C 函数中获取一个 int 和 string。 int - 错误代码,string - 数据。

这样试过:

package main
/*
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int test(char *out){
  snprintf(out, sizeof out, "1234567890abcd");
  return 0;
}

*/
import "C"

import (
  "fmt"
  "unsafe"
)

func main() {
  foo := C.CString("")
  defer C.free(unsafe.Pointer(foo))
  C.test(foo)
  fmt.Println("Output is: "+C.GoString(foo))
}

几乎成功了。

Output is: 1234567

但应该是:1234567890abcd

我认为传递给 C 函数的 C.String 的大小是 8。 但不知道如何扩展它(固定大小 <> 8)或更改为动态。

所以问题是:我应该如何将该变量传递给 C?

您正在指针上调用函数 sizeof。指针的大小在您的计算机上是 8 个字节,因此您将返回一个长度为 8 的字符串。

我不知道您应该如何精确管理指针大小的所有细节,因为我不太擅长 C,但这个示例说明了如何解决您的紧迫问题。

package main
/*
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int test(char *out){
  snprintf(out, 16, "1234567890abcd");
  return 0;
}

*/
import "C"

import (
    "fmt"
    "unsafe"
)

func main() {
    foo := C.CString("")
    defer C.free(unsafe.Pointer(foo))
    C.test(foo)
    fmt.Println("Output is: "+C.GoString(foo))
}

经过研究我找到了解决方案:

package main


/*
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int test(char *out, int len){
  snprintf(out, len, "1234567890123456789012345671`iknvcap9nv1-93hbf1-39b");
  return 0;

}

*/
import "C"

import (
  "fmt"
  "unsafe"
)

func main() {
  buf := make([]byte, 8192)
  C.test((*C.char)(unsafe.Pointer(&buf[0])), C.int(len(buf)))
  fmt.Println(string(buf))
}

要从 C 函数接收 'string',我必须创建一个切片:

  buf := make([]byte, 8192)

并传递一个指向它的指针:

  C.test((*C.char)(unsafe.Pointer(&buf[0])), C.int(len(buf)))

在那种情况下使用 C.String 是行不通的。

对于以后遇到此问题的任何人,C.CString 确实有效,只是不能将 sizeof 与指针一起使用,因为它始终为 8 个字符。我是通过以下方式做到的:

package main

/*
#include <stdlib.h>
#include <string.h>

int test(char* out){
  strcpy(out, "1234567890123456789012345671`iknvcap9nv1-93hbf1-39b");
  return 0;
}

*/
import "C"

import (
    "fmt"
    "unsafe"
)

func main() {
    foo := C.CString("")
    defer C.free(unsafe.Pointer(foo))
    C.test(foo)
    fmt.Println("Output is: " + C.GoString(foo))
}