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
|