Golang中如何从C/C++调用包含字符串和map类型字段的结构体函数
Golang中如何从C/C++调用包含字符串和map类型字段的结构体函数
我们的需求是在C++代码中调用Golang库中的函数。目前我们正在使用 -buildmode=c-shared 构建库。
Golang库中的函数使用结构体作为输入和输出。例如:
type Request struct {
X string
Y string
Z map[string]string
}
如果我尝试使用C结构体,它不支持字符串和映射类型,这使事情变得复杂。 https://play.golang.org/p/Qjuu5j2nAv1
我们已经使用protobuf来序列化和反序列化这些复杂的结构体。是否有其他替代方案?因为使用protobuf使得在另一个Golang项目中将此共享Go源码作为库使用变得困难。
更多关于Golang中如何从C/C++调用包含字符串和map类型字段的结构体函数的实战教程也可以访问 https://www.itying.com/category-94-b0.html
map 是一个指针类型,因此你可以将 map[string]string 视为 C 语言中的 void *,然后在 Go 中编写一些简单的函数,并从 C 语言中调用这些函数来执行 Get、Put、Keys 等操作。这些函数接收一个 unsafe.Pointer 参数,将其转换为正确的 map 类型并执行相应的操作。
func main() {
fmt.Println("hello world")
}
更多关于Golang中如何从C/C++调用包含字符串和map类型字段的结构体函数的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
一种可行的方案是使用CGO通过指针传递序列化数据,结合Go的反射机制在Go端重建结构体。以下是具体实现示例:
// export_request.go
package main
import (
"C"
"encoding/json"
"unsafe"
)
// Request 结构体定义
type Request struct {
X string `json:"x"`
Y string `json:"y"`
Z map[string]string `json:"z"`
}
//export ProcessRequest
func ProcessRequest(cData *C.char, cLen C.int) *C.char {
// 将C字符串转换为Go字节切片
goData := C.GoBytes(unsafe.Pointer(cData), cLen)
// 反序列化JSON到Go结构体
var req Request
if err := json.Unmarshal(goData, &req); err != nil {
return C.CString("")
}
// 处理请求(示例)
req.X = "processed_" + req.X
if req.Z == nil {
req.Z = make(map[string]string)
}
req.Z["status"] = "completed"
// 序列化结果
result, _ := json.Marshal(req)
return C.CString(string(result))
}
func main() {}
C++调用端示例:
// main.cpp
#include <iostream>
#include <cstring>
extern "C" {
char* ProcessRequest(const char* data, int length);
}
int main() {
// 准备JSON数据
const char* json_data = R"({
"x": "test1",
"y": "test2",
"z": {"key1": "value1"}
})";
// 调用Go函数
char* result = ProcessRequest(json_data, strlen(json_data));
std::cout << "Result: " << result << std::endl;
// 释放Go返回的字符串
free(result);
return 0;
}
构建命令:
# 构建Go共享库
go build -buildmode=c-shared -o librequest.so export_request.go
# 编译C++程序
g++ -o main main.cpp -L. -lrequest
另一种方案是使用C结构体配合辅助函数:
// export_request2.go
package main
import "C"
import (
"unsafe"
)
// C兼容的结构体
type CRequest struct {
x *C.char
y *C.char
keys **C.char
values **C.char
count C.int
}
//export ProcessRequest2
func ProcessRequest2(req *CRequest) *C.char {
// 转换字符串
x := C.GoString(req.x)
y := C.GoString(req.y)
// 转换map
z := make(map[string]string)
if req.count > 0 {
keys := unsafe.Slice(req.keys, int(req.count))
values := unsafe.Slice(req.values, int(req.count))
for i := 0; i < int(req.count); i++ {
key := C.GoString(keys[i])
value := C.GoString(values[i])
z[key] = value
}
}
// 创建Go结构体
request := Request{
X: x,
Y: y,
Z: z,
}
// 处理逻辑
request.X = "modified_" + request.X
// 返回结果(示例)
return C.CString(request.X)
}
func main() {}
这些方案避免了protobuf的依赖,同时保持了Go结构体的完整性。JSON方案更通用,C结构体方案性能更好。

