如何将C++的const char[]或std::string正确转换为Go的GoString?
解决C++与Go互调时的字符串类型转换问题
问题背景
要从C++调用Go实现的语言检测函数,Go代码如下:
// basic.go package main import "C" import ( "github.com/pemistahl/lingua-go" ) var lan lingua.Language //export Langdetectfunct func Langdetectfunct(text string) int { detector := lingua.NewLanguageDetectorBuilder(). FromAllLanguages(). Build() if language, exists := detector.DetectLanguageOf(text); exists { lan = language } lan = lingua.English return int(lan) } func main() {}
使用c-shared模式编译生成共享库:
go build -o basic.so -buildmode=c-shared basic.go
尝试在C++中调用时,无论是直接用字符串字面量赋值GoString,还是传入std::string,都会出现类型转换错误:
- 用字符串字面量赋值时错误:
error: conversion from ‘const char [22]’ to non-scalar type ‘GoString’ {aka ‘_GoString_’} requested - 传入
std::string时错误:error: could not convert ‘text’ from ‘std::string’ {aka ‘std::__cxx11::basic_string<char>’} to ‘GoString’ {aka ‘_GoString_’}
解决方案
Go生成的头文件中,GoString是一个结构体,定义大致如下:
typedef long long GoInt; typedef struct { const char *p; GoInt n; } GoString;
它包含两个字段:p是字符串指针,n是字符串长度。需要手动构造该结构体,不能直接用C++字符串类型赋值。
1. 从C++字符串转换为GoString
从const char[]转换
直接用字符串指针和strlen获取的长度构造GoString:
const char* c_text = "Languages are awesome"; GoString go_text = {c_text, strlen(c_text)};
从std::string转换
利用std::string的c_str()方法获取指针,size()方法获取长度:
std::string cpp_text = "Languages are awesome"; GoString go_text = {cpp_text.c_str(), static_cast<GoInt>(cpp_text.size())};
修改后的完整C++代码:
#include "basic.h" #include <iostream> #include <cstring> // 用于strlen函数 int main() { // 从const char[]转换调用 const char* c_text = "Languages are awesome"; GoString go_text1 = {c_text, strlen(c_text)}; int res1 = Langdetectfunct(go_text1); std::cout << "res1: " << res1 << std::endl; // 从std::string转换调用 std::string cpp_text = "Languages are awesome"; GoString go_text2 = {cpp_text.c_str(), static_cast<GoInt>(cpp_text.size())}; int res2 = Langdetectfunct(go_text2); std::cout << "res2: " << res2 << std::endl; return 0; }
2. 从GoString转换为C++字符串
如果需要将Go返回的GoString转换为C++类型:
- 转换为
std::string:直接利用std::string的构造函数,指定指针和长度:std::string cpp_str(go_str.p, go_str.n); - 转换为
const char[]:直接使用go_str.p即可,但要注意内存生命周期,避免引用Go已回收的内存。
编译注意事项
编译C代码时,不要用C语言的标准参数-std=c17,应该用C的标准参数:
g++ -std=c++17 -o basic basic1.cpp ./basic.so
内容的提问来源于stack exchange,提问作者Raphael10
相关产品推荐
相关产品推荐

