Kotlin调用C函数时出现两类Swig报错 寻求解决方案
Swig生成Java接口两类报错解决
第一类:Swig解析阶段找不到标准头文件
执行命令:
swig -java -includeall -package onescream.onescream compute_feature_set.i
报错内容:
compute_feature_set.h:17: Error: Unable to find 'stddef.h' compute_feature_set.h:18: Error: Unable to find 'stdlib.h'
原因
加了-includeall参数后,Swig会递归解析所有#include引入的头文件,包括C标准库头,但Swig不会默认读取系统C标准库的头文件路径,且Swig本身不需要解析标准库的具体实现,只需要识别基础类型定义即可。
解决方法
- 优先直接去掉
-includeall参数,绝大多数业务场景不需要递归解析所有依赖头,Swig自带的基础类型映射已经可以处理头文件里用到的标准库类型。 - 如果必须保留
-includeall参数,在接口文件compute_feature_set.i的最开头添加两行:
%include "stddef.i" %include "std_common.i"
这两个是Swig自带的标准库类型定义文件,不需要依赖系统路径下的.h文件。
第二类:链接阶段报未定义符号错误
执行构建命令序列:
swig -java compute_feature_set.i gcc -c compute_feature_set.c compute_feature_set_wrap.c -I/Users/fas/Library/Java/JavaVirtualMachines/openjdk-18.0.1.1/Contents/Home/include -I/Users/fas/Library/Java/JavaVirtualMachines/openjdk-18.0.1.1/Contents/Home/include/darwin gcc -shared compute_feature_set.o compute_feature_set_wrap.o -o libcompute_feature_set.so
报错内容:
Undefined symbols for architecture arm64: "_b_fft", referenced from: _compute_feature_set in compute_feature_set.o "_binary_expand_op", referenced from: _compute_feature_set in compute_feature_set.o "_eml_find", referenced from: _compute_feature_set in compute_feature_set.o ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
原因
该错误和Swig本身无关,属于C链接阶段错误:编译时仅加入了业务代码compute_feature_set.c和Swig生成的包装代码compute_feature_set_wrap.c,但上述三个未定义符号来自外部依赖库,没有被加入编译/链接流程。从函数名判断,_eml_find属于边缘机器学习库、_b_fft属于FFT实现库,都是compute_feature_set.c依赖的外部代码。
解决方法
- 先定位三个函数的实现位置:查找项目中是否包含这些函数对应的
.c源文件,或者提前编译好的静态库.a/动态库.dylib文件。 - 如果是源码形式的依赖,把所有依赖的
.c文件全部加入编译命令,再把生成的所有.o文件全部加入链接命令,示例:
# 编译阶段加入所有依赖的源文件,比如eml.c、fft.c是依赖实现 gcc -c compute_feature_set.c compute_feature_set_wrap.c eml.c fft.c -I/Users/fas/Library/Java/JavaVirtualMachines/openjdk-18.0.1.1/Contents/Home/include -I/Users/fas/Library/Java/JavaVirtualMachines/openjdk-18.0.1.1/Contents/Home/include/darwin # 链接阶段把所有生成的目标文件打包 gcc -shared compute_feature_set.o compute_feature_set_wrap.o eml.o fft.o -o libcompute_feature_set.so
- 如果是预编译好的静态库/动态库,在链接阶段通过
-L指定库文件路径,-l指定库名,示例(假设依赖库存放在当前目录的lib文件夹下,库名为eml):
gcc -shared compute_feature_set.o compute_feature_set_wrap.o -L./lib -lemL -o libcompute_feature_set.so
注意:当前环境为arm64架构的Mac设备,必须确认依赖的预编译库也是arm64版本,x86_64版本的库同样会触发符号找不到、架构不匹配的错误。
内容的提问来源于stack exchange,提问作者FerasAS
相关产品推荐
相关产品推荐

