文章目录
测试环境描述
以下内容所使用环境ubuntu、jdk1.8
本文文件描述
Test.java
主要完成的功能是使用生成jni对应的Test.h,新建Test.cpp写入内容,再去生成libTest.so,然后在Java类中加载
fingerprintExtract.cpp
c++的一些功能类,为了方便在Test.cpp中被使用,把该文件编译成对应的.so库
fftw
在fingerprintExtract.cpp被使用,一个开源库,.configure、make的时候会生成.so库
jni的描述
JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植
编译在后面使用到的fftw库
./configure --prefix=/home/zy/test/zengraoli_jni_plus/fftw-3.3.8/output --enable-shared
make -j32
make install
修改库的搜索路径,或者把libfftw3.so.3拷贝到/usr/local/lib中,并重命名为libfftw3.so
修改库路径的两种方法
第一种方法,修改库路径
sudo vim /etc/ld.so.conf
在最后一行插入
/home/zy/test/zengraoli_jni_plus/fftw-3.3.8/output/lib
编辑完成之后使用
sudo ldconfig
更新一下
第二种方法,拷贝到/usr/local/lib
sudo cp libfftw3.so.3 /usr/local/lib/libfftw3.so
生成Java调用的入口点
写对应的Java文件Test.java
public class Test
{
static
{
System.load("/home/zy/test/zengraoli_jni_plus/libTest.so"); //libmain.so是jni要生成的so文件
}
public native void extractFingerPrint(String inputVoices, String dataHash); // 声明jni导出的函数 //声明的add()函数,在后面他封装了类Twono中的Add()函数
public static void main(String[] args)
{
String inputVoices = "/home/zy/migudata/source/";
String dataHash = "/home/zy/fingerPrint/fingerprint/data/hash709.txt";
Test main = new Test();
main.extractFingerPrint(inputVoices,dataHash); // 调用jni导出的函数extractFingerPrint
}
}
用Java文件生成jni对应头文件Test.h
javac Test.java
javah Test
补充Test.cpp文件
写入以下内容
#include "stdio.h"
#include "Test.h"
#include <fstream>
#include <string>
#include <time.h>
#include "fingerprintExtract.h"
using namespace std;
JNIEXPORT void JNICALL Java_Test_extractFingerPrint
(JNIEnv *env, jobject obj, jstring inputVoices, jstring dataHash)
{
printf("zengraoli begin.\r\n");
const char *input = env->GetStringUTFChars(inputVoices, NULL);
string inputPath = input;
env->ReleaseStringUTFChars(inputVoices, input);
const char *data = env->GetStringUTFChars(dataHash, NULL);
string dataPath = data;
env->ReleaseStringUTFChars(dataHash, data);
fingerprintExtract fingerprintTemp;
fingerprintTemp.fingerprintVoices(inputPath , dataPath);
printf("zengraoli end.\r\n");
}
fingerprintExtract.h的内容如下
#pragma once
#include "hash.h"
#include "fingerprint.h"
#include "FileChange.h"
#include "time.h"
#include <dirent.h>
//#include <Windows.h>
//#include <io.h>
class fingerprintExtract {
private:
public:
void fingerprintVoices(string inputVoices, string dataHash);
void ProcessVoices(const char *voicesPath);
};
fingerprintExtract.cpp主要涉及到一些业务操作,依赖fftw这个库,所以代码可以任意
在linux上面编译生成fingerprintExtract.so
fingerprintExtract.cpp在生成的.so的时候,依赖了hash、fingerprint、FileChange,这几个文件需要在生成时候一块编译
g++ -fPIC -shared -o libfingerprintExtract.so FileChange.cpp wav.cpp hash.cpp fingerprint.cpp fingerprintExtract.cpp
用
ldd -r libfingerprintExtract.so
查看一下.so,发现这个时候是没有引入fftw.a造成函数找不到的问题
但其他的函数都正确了
那么只需要在生成Test.so的时候把这个.a库链接进来即可
生成jni对应的so文件
g++ -fPIC -I/home/wfx/usr/java/jdk1.8.0_111/include -I/home/wfx/usr/java/jdk1.8.0_111/include/linux -I/home/zy/test/zengraoli_jni_plus/fftw-3.3.8/output/include -L/home/zy/test/zengraoli_jni_plus/fftw-3.3.8/output/lib -L. -shared -o libTest.so -lfftw3 -lfingerprintExtract Test.cpp
查看libTest是否有函数找不到链接
ldd -r libTest.so
执行Java文件中的main查看对应的函数是否被调用
可以看到,调用已经没有问题了
判断.so文件是否为debug版本
readelf -S libTest.so
如果没有看到有debug字段,那么则直接就是release对应的.so文件