在项目中需要用Java调用c++编写的dll库,以前了解过JNI的用法,后来发现JNA使用起来更加方便,缺点是不能在C++端调用Java端,但对于项目需求而言已经足够了。简单记录下JNA的用法。
JNA调用C的库函数输出“Hello world!”:
public class JnaTest {
// This is the standard, stable way of mapping, which supports extensive
// customization and mapping of Java to native types.
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
CLibrary.class);
void printf(String format, Object... args);
}
public static void main(String[] args) {
CLibrary.INSTANCE.printf("Hello, World\n");
for (int i=0;i < args.length;i++) {
CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
}
}
}
JNA调用C函数的方式很简单,示例通过调用C语言中的printf函数实现输出“HelloWorld!”。
现在尝试调用自己编写的dll,在vs2013中编写dll,示例代码如下:
// AddDemo.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
extern "C"_declspec(dllexport) int add(int a, int b);
int add(int a, int b) {
return a + b;
}
需要注意的是,如果jdk的版本是32位的,则只能调用32的dll,若是64位的,则调用64位的dll。因为项目采用的Java是64位版本的,所以生成配置如下:
dll生成成功后即可通过Java调用:
public class DllTest {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)Native.loadLibrary("D:\\dll\\AddDemo.dll", CLibrary.class);
int add(int a, int b);
}
public static void main(String[] args) {
int sum = CLibrary.INSTANCE.add(3, 6);
System.out.println(sum);
}
}
定义接口加载dll库,在接口中声名要调用的函数名称,然后直接调用就可以了。
如果C中的函数用__stdcall声名过了,则接口需要继承StdCallLibrary,本项目中的dll功能是调用声卡来播放获取的音频数据,测试代码如下:
public class AudioRead {
public interface CLibrary extends StdCallLibrary {
CLibrary INSTANCE = (CLibrary)Native.loadLibrary("D:\\dll\\EVAL_Audio.dll", CLibrary.class);
int WriteAudioDataParams();
int WriteAudioData(double[] dOut);
}
public static void main(String[] args) {
CLibrary.INSTANCE.WriteAudioDataParams();
String path = "D:\\audioData";
File file = new File(path);
String[] filelist = file.list();
for(int i=0;i<filelist.length;i++){
File readfile = new File(path + "\\" + filelist[i]);
double[] data = readData(readfile);
CLibrary.INSTANCE.WriteAudioData(data);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private static double[] readData(File file){
double[] data = null;
try{
Scanner sc = new Scanner(file);
List<Double> doubles = new ArrayList<Double>();
while (sc.hasNextDouble()) {
doubles.add(sc.nextDouble());
}
data = new double[doubles.size()];
for(int i=0;i<doubles.size();i++){
data[i] = doubles.get(i);
}
}catch(Exception e){
e.printStackTrace();
}
return data;
}
}