0%

【Linux技术分享】cgo传入二级指针

cgo实现字符串切片传入c代码中

go实现字符串切片传入c代码中,让c识别为二级指针,能够顺利进行字符串的偏移读写

起因

想通过go给C代码传入一个二级指针,然后在C中进行读取,本来以为是很简单的事情,但是发现go的string和c++的不太一样,C的代码如下

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <string.h>

void fill_2d_array(char **arr, int columeSize) {
char szBuf[4][255];
for(int i = 0;i < 4;i++) {
strcpy(szBuf[i], arr[i]);
printf("buf:%s\n", szBuf[i]);
}
}

第一次转换的写法

1
2
3
4
5
6
7
8
9
10
func byteToC(list []string) {
dirs := make([][]byte, 4)
for i := 0; i < 4; i++ {
dirs[i] = make([]byte, 4)
dirs[i] = []byte(list[i])
fmt.Println("list:", list[i])
}

C.fill_2d_array((**C.char)(unsafe.Pointer(&dirs[0][0])), C.int(5))
}

把切片转成byte传入C的代码中,但是在C代码输出的时候直接输出直接崩溃,如果按照字节处理strcpy((char*)(arr+0*sizeof(char)*columeSize), "hello");类似这种处理,但是在C中输出的时候,字符串会或多或少,不能正常输出。

根因分析:之前我写过go转C++的dll,导出头文件关于GoString的定义为

1
2
3
#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef struct { const char* p; ptrdiff_t n; } _GoString_;
#endif

这边我直接输出了printf("%s",goString.p);,然后是一串很长的字符串,详情看如何生成dll的请移步利用go搭建纯文件http服务器,并生成dll,这边判断gostring中的p在转换的时候没有保存’\0’,意思就是没有结束符,把后面的东西全部都输出了

第二次转换的写法

问题找到了,只需要把’\0’在传入的时候传过去就OK,于是放弃转byte的转换方法,改用C.char*.

1
2
3
4
5
6
7
8
func charToC(list []string) {
nameunits := make([]*C.char, len(list))
for i, _ := range list {
nameunits[i] = C.CString(list[i])
}

C.fill_2d_array((**C.char)(unsafe.Pointer(&nameunits[0])), C.int(4))
}

输出正常圆满完成任务

1
2
3
4
buf:1111
buf:2222
buf:3333
buf:4444