一、前言
最近这家公司有个大客户,需求非常苛刻。我们这边提供的是sdk, 用来操作硬件设备,一般提供的是动态库dll, 一般也是只提供windows平台的。
实际需求跨端,跨平台。要求,提供web 端spring boot 后台功能,桌面端 javafx 功能,然后,又提说他们的生产环境是windows ,实际部署环境是linux, 因此,又要求提供的web 端和 桌面端的工程,能在linux 上运行。
所以,综合需求是,要求我写的提供一套spring boot java 后台代码,能windows 上运行,也能在linux 上运行。桌面端java fx 代码也是如此,两个平台都能运行。
java 本来就是跨平台,所以不用太担心,只要写好一套后台代码和前端代码就可以。但是,与硬件设备通讯的底层代码,就不是跨平台的,每套系统,都有自己独有的API,
这部分是不能跨平台的,必须各自编写底层代码。
JAVA代码跨平台,为了统一接口,所以使用jni, linux 和 windows 都各自使用jni 统一java 接口这样子java 只需一套代码即可。
二、问题
在windows jni 编译测试通过后,将web 工程,和 javafx 工程,提供给客户测试通过后,然后着手开始linux jni 底层代码编写,将windows 代码也是如此,两个平台都能运行。成功
移植到linux 平台,通过编译后,使用java 代码测试,出现一个bug。
/usr/local/java/eclipse/plugins/org.eclipse.justj.openjdk.hotspot.jre.full.linux.x86_64_17.0.2.v20220201-1208/jre/bin/java: symbol lookup error:
libtest.so: undefined symbol: _ZN7ComPortC1Ev
但是代码事先是使用linix 控制台测试通过后,才在java 代码上测试的,
所以,代码应该没有问题,而且代码都是从windows 上移植过来的, windows 平台都是通过测试的。
这个问题就棘手了。
经过网络搜索,发现在这篇文章中,有相似问题。
undefined symbol问题的查找、定位与解决方法
比对发现,这个问题是符号未定义问题,即jni so导出的函数符号异常。通过问题定位,出现c++ 代码中,调用一句
parity = tmp[0] - '0';
databits = tmp[1];
stopbits = tmp[2] - '0';
ComPort *_Com = new ComPort; //这句代码出现问题
//打开连接成功
// if (_Com->Connect(comname, baud, parity, databits, (stopbits - 1)))
if (_Com->Connect(comname, baud, parity, databits, stopbits))
然后,再次详细检查这部分代码,确认没有问题,所以,应该不是代码层的问题。
然后检查,生成的各个 libtest.so 库文件,查看导出和依赖的函数,发现目标调用的 libtest.so 文件依赖的一个函数,即这句代码
ComPort *_Com = new ComPort; //这句代码出现问题
依赖的类没有参与编译,然后查看生成库文件的 CMakeLists.txt 配置代码,发现确实这个类对应的文件没有参与编译,这个
#增加源文件
set(SRC
./../public/comm/CommTransport.cpp
./../public/comm/NetWork.cpp
./src/device.cpp
)
因此,修改CMakeLists.txt ,增加对应类,重新编译后,问题解决。
/**
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████ ┃+
* ┃ ┃ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃
* ┃ ┃ + + + +
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ + 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃ +
* ┃ ┗━━━┓ + +
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*
* @author chenxi
* @date 2022-5-10 10:46:02
*/