前言: 众所周知,Go是存在多返回值的,但C/C++只有单返回值处理,当他们需要跨平台合作时,该怎么处理呢?
目标: 借助.so文件,使得C可以获取Go方法中的多返回值
举例及解决方案:
比如我们要求调用Go方法,要求的输入和输出类型分别是:
输入 | 输出 | ||
字符串类型 | 整数类型 | 字符串类型 | 无符号整数类型 |
CGO要求的一些基础注意事项在很多博客中都有,这里就简单提下:
import "C"
一定要紧挨着其他import
方法上方一定要写//export 方法名
注意CGO的类型转换【参考】
多返回值的处理办法:写成结构体格式(是C的结构体哦)
结构体定义写在 import "C"
的上方(紧挨)
/*
struct X_test_data
{
int v1;
char *v2;
unsigned int v3;
};
*/
import "C"
import (
...
)
Go方法返回值调用该结构体
//export x_test
func x_test(in *C.char) C.struct_X_test_data {
inString := C.GoString(in) // *C.char转string类型
out := "string"
// 各种处理...
return C.struct_X_test_data{
v1: 1,
v2: C.CString(out), // string转*C.char类型
v3: C.uint(len(out)),
}
}
编译生成.so文件和.h文件,之前有讲~
C调用(不需要自定义结构体,直接使用),顺利取出三个值!
struct X_test_data r = x_test("string");
printf("v1: %d,\nv2: %s,\nv3: %ld\n", r.v1, r.v2, r.v3);
原因探索:
观察生成的.h文件,可以发现该结构体作为头文件被编译出来了
struct X_test_data
{
int v1;
char *v2;
unsigned int v3;
};
extern __declspec(dllexport) struct X_test_data x_test(char* in);
因此,C文件可以从.h文件中读取到该结构体定义而不需要单独定义,保证了跨平台一致性(其实就是共享定义嘛~)