我正在尝试使用返回切片的函数构建go共享库。
如何使用C代码中的切片?
package main
import "C"
type T struct {
A C.int
B *C.char
}
//export Test
func Test() []T {
arr := make([]T, 0)
arr = append(arr, T{C.int(1), C.CString("a")})
arr = append(arr, T{C.int(2), C.CString("abc")})
return arr
}
func main() {}
go build -o lib.so -buildmode=c-shared main.go
我现在有一个lib.so
和一个lib.h
打印数组值的C代码是什么?
#include <stdio.h>
#include "lib.h"
typedef struct {
int A;
char* B;
} T;
int main() {
GoSlice a = Test();
for (int i = 0; i < 2; i++){
printf("%s\n", ((T *)a.data)[i].B);
}
}
gcc -o main main.c ./lib.so
答案 0 :(得分:0)
在C语言中使用Go切片
以下是C打印Go byte
切片的示例:
package main
/*
#include <stdio.h>
void printbuf(size_t len, unsigned char *buf) {
printf("%lu [", len);
if (!buf) {
len = 0;
}
size_t maxwidth = 16;
size_t width = len <= maxwidth ? len : maxwidth;
for (size_t i = 0; i < width; i++) {
if (i > 0) {
printf(" ");
}
printf("%02X", buf[i]);
}
if (width < len) {
printf(" ...");
}
printf("]\n");
}
*/
import "C"
func cbuf(buf []byte) (size C.size_t, ptr *C.uchar) {
var bufptr *byte
if cap(buf) > 0 {
bufptr = &(buf[:1][0])
}
return C.size_t(len(buf)), (*C.uchar)(bufptr)
}
func main() {
buf := make([]byte, 24, 32)
for i := range buf {
buf[i] = byte(i)
}
bufsize, bufptr := cbuf(buf)
C.printbuf(bufsize, bufptr)
}
输出:
24 [00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ...]
func Test() []T
的C返回值错误。返回长度和数组指针,例如cbuf
。
答案 1 :(得分:0)
首先,C不了解Go slice的类型,也不知道如何操作它,因此您应该像在C中一样返回数组指针。
您也不能在Go中分配切片,然后返回指向已分配内存的指针,而无需采取任何措施防止其被GC处理。在此示例中,仅使用C分配数组可能更简单。
p := C.malloc(C.size_t(2))
// make a slice for convenient indexing
arr := (*[1 << 30]*T)(p)[:2:2]
arr[0] = &T{C.int(1), C.CString("a")}
arr[1] = &T{C.int(2), C.CString("abc")}
return p
当然,您还需要处理数组大小,可以通过将其组合到一个结构中来处理数组大小,就像处理字符串一样,或者接受第二个指针参数设置为返回大小。
不要忘记,由于您正在C中分配内存,因此您还负责释放它。这既适用于malloc
调用,也适用于C.CString
数组。