最近在做百度的离线人脸识别 ,官方只给出了C++的SDK,但是我用的平台是Java的,没办法,只能自己转换了,思路就是将SDK的接口封装一下,然后打包成动态链接库dll让Java调用,之间的联系可以用JNI或者JNA,JNI偏向底层,设置很繁琐但是性能较高,JNA是基于JNI封装的一个库,使用非常简单,这次就用JNA来调用dll。
附上JNA的地址:https://github.com/java-native-access/jna
封装比较简单,参数和返回值按照类型对照表一一对应即可,JNA的使用网上也有教程。
JNA类型对照表和使用教程:https://blog.csdn.net/abc6368765/article/details/77842066
但是在C++的数组上出现了问题,一开始以为C++和Java的数组类型都是一样的,直接用C++的float[]对应Java的float[],但是发现错误,不可行,查找资料发现C++的数组类型在内存中是连续存储的,而Java的数组不一定是连续的,按照对照表,C++的数组指针应该对应Java的ByReference引用对象,它类似C的指针,使用它就能正常转换了,下面附上流程。
首先是对照表:
C Java
char ByteByReference
int IntByReference
float FloatByReference
double DoubleByReference
转换流程,其中Xxx代表类型。
读取、写入单个元素:
XxxByReference的getValue()和setValue(Xxx value)方法即可
读取整个数组:
由于默认对象只有1个元素,这时候我们需要重写类
仿照XxxByReference类,继承ByReference,构造方法的super(int size)要改成你的数组大小
public class ByteByReference extends ByReference {
public ByteByReference() {
this((byte)0);
}
public ByteByReference(byte value) {
super(1);
this.setValue(value);
}
public void setValue(byte value) {
this.getPointer().setByte(0L, value);
}
public byte getValue() {
return this.getPointer().getByte(0L);
}
}
切记!ByReference对象要在Java中new出来后作为参数传入C++,用C++函数直接写数组即可。不能用C++的指针返回ByReference对象,否则可能出现ByReference对象和C++的不是同一个指针。
然后使用XxxByReference.getPointer().getXxxArray(int offset,int size)方法即可
其中offset表示从哪一个数组下标开始,size表示读取元素数目
这样C++的数组就转换成Java的数组了。