【问题标题】:How to add a golang string to a c struct in cgo如何将golang字符串添加到cgo中的c结构
【发布时间】:2021-11-15 19:18:44
【问题描述】:

如何将 golang 字符串添加到我在 cgo 中创建的 c 结构中。代码如下:

package main

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

typedef struct Point {
    int x, y;
} Point;

typedef struct Resp {
    char response;
} Resp;
*/
import "C"
import (
    "fmt"
    "io/ioutil"
    "unsafe"
)

type CPoint struct {
    Point C.Point
    Resp  C.Resp
}

func main() {

    var r string = "Hello World"
    resp := unsafe.Pointer(C.char(r))

    point := CPoint{
        Point: C.Point{x: 1, y: 2},
        Resp: C.Resp{response: resp},
    }
    fmt.Println(point)
}

但是每当我运行它时,我都会收到此错误 cannot convert r (type string) to type _Ctype_char 我该如何解决?如何将 r 转换为类型 _Ctype_char?

另外,你将如何获得 c 结构“Resp”中的值?

package main

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

typedef struct Point {
    int x, y;
} Point;

typedef struct Resp {
    char response; // <-- How can I get this value in my go code?
} Resp;
*/

【问题讨论】:

  • 不能用r := "hello world"吗?
  • 同样的事情,仍然报同样的错误。

标签: c go cgo


【解决方案1】:

您的代码需要 2 处修复:

  1. C char 仅表示单个字符/字节 - 而不是字符串。 C 字符串是char*
  2. 你应该使用C.CString从Go中分配一个C字符串,使用C.free释放它。请参阅:https://pkg.go.dev/cmd/cgo#hdr-Go_references_to_C

以下是您的修复示例:

package main

// FIX: "char response" replaced with "char *response" below.

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

typedef struct Point {
    int x, y;
} Point;

typedef struct Resp {
    char *response;
} Resp;

void fill(const char *name, Resp *r) {
   printf("name: %s\n", name);
   printf("Original value: %s\n", r->response);
   r->response = "testing";
}
*/
import "C"
import (
    "fmt"
    "unsafe"
)

// NOTE: You cannot pass this struct to C.
// Types passed to C must be defined in C (eg, like "Point" above).
type CPoint struct {
    Point C.Point
    Resp  C.Resp
}

func main() {
    // FIX: Use CString to allocate a *C.char string.
    resp := C.CString("Hello World")

    point := CPoint{
        Point: C.Point{x: 1, y: 2},
        Resp:  C.Resp{response: resp},
    }
    fmt.Println(point)

    // Example of calling a C function and converting a C *char string to a Go string:
    cname := C.CString("foo")
    defer C.free(unsafe.Pointer(cname))
    r := &C.Resp{
        response: resp, // Use allocated C string.
    }
    C.fill(cname, r)
    goResp := C.GoString(r.response)
    fmt.Println(goResp)

    // FIX: Release manually allocated string with free(3) when no longer needed.
    C.free(unsafe.Pointer(resp))
}

【讨论】:

  • 谢谢它的工作!但是如何将 C 结构中的值重新检索到 go 中?
  • 您可以使用C.GoString*C.char 转换为Go string。否则,我不确定你需要什么。您能否更详细地更新您的问题?
  • 比如如何从我创建的 C 结构中获取值并在 go 中返回它?还更新了问题
  • 我刚刚通过调用 C 函数并复制 char* 字符串以便可以在 Go 中使用的示例更新了答案。这有帮助吗?我怀疑您实际上想在 C 中定义您的 CPoint 结构,然后您可以将其称为 C.Point。你不能将 Go 结构传递给 C 函数。
  • 感谢您的示例!但是我如何从 C 的结构中获得响应,因为结果是“测试”
猜你喜欢
  • 2019-06-03
  • 2016-12-25
  • 2019-08-26
  • 2015-12-24
  • 2019-01-14
  • 2013-09-22
  • 2020-07-26
  • 1970-01-01
  • 2016-03-21
相关资源
最近更新 更多