Linux下JAVA调用C++动态库

公司项目要求对接腾讯云的实时音视频(Tencent Real-Time Communication,TRTC),其开发语言是C++,需封装成java接口。以前没有做过类似的项目,边踩坑边学习,目前思路基本捋顺,记录一下备忘。

腾讯提供了以下文件:

*libTRTCEngine.so*  C++业务实现底层核心代码编译而成的动态库文件。
*recordsdk.i*  swig接口文件,c++转java指令文件
*convert.sh*  shell脚本,后续会说明。
一系列C++的.h头文件
一、用swig生成java类和C++接口的wrap文件

1.安装swig

2.执行命令

swig -c++ -java -package com.tencent -outdir ./ -Irecordsdk.i
说明:
-c++ -java   告诉swig是C++转java
-package   生成的java的包名
-outdir   生成文件的输出地址
-I  .i文件路径(文件名必须紧跟参数)。

3.生成文件
执行完上述命令后,会生成以下几个文件:

*recordsdk_wrap.cxx*    c++文件,包装器文件,将C++的类的方法转成C语言的函数
*Trtcengine.java*    .i文件中,与modul同名的类。(腾讯提供的.i文件module名首字母小写,需改成大写才能符合java规范)
*TrtcengineJNI.java*    c++类中的方法在此文件中转为java的静态方法,就是JAVA中的native方法
其他C++类对应的java类文件
二、生成so动态库文件

执行命令,将recordsdk_wrap.cxx编译成so动态库文件。

g++ -std=c++11 -fPIC -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -L../lib -lTRTCEngine recordsdk_wrap.cxx -shared -v -o libtrtcengine.so
简单说明:
-std    声明C++语言版本
-fPIC    用于生成位置无关代码
-I    跟JNT所在路径,通常是在jdk安装路径的include下
-L    链接第三方库。这里链接的是腾讯提供的libTRTCEngine.so(注意大小写)
-o    生成的so库的路径以及命名。(注意大小写)

最后生成的动态库文件为 libtrtcengine.so。(腾讯提供的动态库文件为libTRTCEngine.so,注意区分)
注意:动态库文件的命名规则是:lib+{name}+.so ,name区分大小写。
腾讯提供的 convert.sh 脚本中便是第二步,第三步所执行的命令集。

三、Java调用动态库

第一步中生成的java代码编译成class文件作为jar包被项目工程调用。当工程调用到其中的native方法时,便会去加载动态库。

System.loadLibrary("trtcengine");

这行代码便是去加载我们生成的 libtrtcengine.so 文件。要注意的是,loadLibrary方法的参数,也就是动态库名,不包含前缀"lib"以及后缀".so"。

注意:库文件 libtrtcengine.so以及它所连接的第三方库文件libTRTCEngine.so都必须放到 java.library.path下面,这样才能被代码和程序识别加载。在linux中,默认的 java.library.path 是/lib或者/usr/lib.
若要存放到自定义目录
方法一:

export LD_LIBRARY_PATH=/usr/...

只在当前session有效,登出后失效。
方法二:
修改etc/profile文件, 在其中添加

export LD_LIBRARY_PATH=/usr/...

然后执行

source profile
四、配置TRTC用户信息

在转换后的EngineWarpper.java中,sdkappid userid usersig这三个变量是写死的,需改成自己的相关信息。

有个疑问,为什么腾讯已经提供了so动态库文件,还要自己生成另外一份动态库文件。我尝试了一下,直接调用腾讯提供的libTRTCEngine.so文件可以加载,但是会抛异常。我的理解是,JNI生成的so库,才能被java调用。

还有一些点不甚明白,一起探讨学习。

记录成长,热爱生活!

你可能感兴趣的:(java)