从C++调用lingua-go生成共享库报错:lingua.Language类型不支持导出
问题分析
你遇到的错误是因为Go的c-shared构建模式只允许导出C语言兼容的基础类型(比如C.int、*C.char这类),而lingua.Language是lingua-go库定义的自定义枚举类型,C无法识别这种类型,所以导出函数时会报错。
修复方案
需要把函数的参数和返回值都改成C能处理的类型,下面给两种实用的修改方式:
方式1:返回语言的字符串标识(推荐)
把检测结果转为ISO 639-1标准代码(比如"en"代表英语,"zh"代表中文)或者语言名称,以C字符串的形式返回。同时优化代码,避免每次调用都重新创建检测器(重复创建会大幅降低性能):
package main import "C" import ( "github.com/pemistahl/lingua-go" ) // 全局检测器,初始化一次即可 var detector lingua.LanguageDetector func init() { detector = lingua.NewLanguageDetectorBuilder(). FromAllLanguages(). Build() } //export Langdetectfunct func Langdetectfunct(text *C.char) *C.char { // 将C传入的字符串转成Go字符串 goText := C.GoString(text) if language, exists := detector.DetectLanguageOf(goText); exists { // 返回ISO 639-1短代码,转成C字符串 return C.CString(language.IsoCode639_1().String()) } // 检测失败时默认返回英语的代码 return C.CString(lingua.English.IsoCode639_1().String()) } func main() {}
⚠️ 注意:C.CString在C的堆内存上分配空间,C++调用完这个函数后,必须用free()释放返回的字符串指针,不然会内存泄漏。
方式2:返回整数枚举值
lingua.Language底层是int类型,可以直接转成C.int返回。C++端需要自己维护整数和语言的映射关系:
package main import "C" import ( "github.com/pemistahl/lingua-go" ) var detector lingua.LanguageDetector func init() { detector = lingua.NewLanguageDetectorBuilder(). FromAllLanguages(). Build() } //export Langdetectfunct func Langdetectfunct(text *C.char) C.int { goText := C.GoString(text) if language, exists := detector.DetectLanguageOf(goText); exists { // 把Language转成C.int返回 return C.int(language) } // 默认返回英语的枚举值 return C.int(lingua.English) } func main() {}
比如在C++里可以定义对应枚举:
enum Language { English = 0, Chinese = 1, // 其他语言对应值参考lingua-go源码 };
重新编译
修改完代码后,再执行原来的编译命令:
go build -o basic.so -buildmode=c-shared basic.go
就能正常生成.so和.h文件了。
内容的提问来源于stack exchange,提问作者Raphael10
相关产品推荐
相关产品推荐

