http://developer.51cto.com/art/201201/311363.htm
最近在用weka做一个数据挖掘相关的项目,不得不说,weka还是一个不错的开放源代码库,提供了很多最常用的分类和聚类算法。
在我的项目中要用到一个聚类算法,Affinity Propagation(AP),由多伦多大学的Brendan J. Frey发表于2007年。相比其他的聚类算法,AP算法的聚类结果更加准确。
在AP的官方网站公布了AP算法的动态链接库,我的目标就是实现在Java工程中调用这个动态链接库。
在网上查了资料,发现,如果仅仅是想调用Windows的Native API还是比较省事的,这里我主要针对第三方dll的调用。
下面进入正题。
这里主要用的方法是JNI。在网上查资料时看到很多人说用JNI非常的复杂,不仅要看很多的文档,而且要非常熟悉C/C++编程。恐怕有很多人在看到诸如此类的评论时已经决定绕道用其他方法了。但是,假如你要实现的功能并不复杂(简单的参数传递,获取返回值等等),我还是支持使用这个方法的。
Java Native Interface,简称JNI,是Java平台的一部分,可用于让Java和其他语言编写的代码进行交互。下面是从网上摘取的JNI工作示意图。
下面就举具体的例子说明一下使用步骤:
(一)JAVA中所需要做的工作
例如程序testdll.java,内容为:
package p1.test
public class testdll
{
//在JAVA程序中,首先需要在类中声明所调用的库名称。在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。
static
{
System.loadLibrary("hello");
}
//还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具体实现。
public native static int get();
public native static void set(int i);
public static void main(String[] args)
{
testdll test = new testdll();
test.set(10);
System.out.println(test.get());
}
}
然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。
其中D:\software\JAVA\android-sdk_r24.0.2\android-sdk-windows\eclipse\workspace\DEMO1\src\p1\test\目录下生成了testdll.java
2.编译生成.h文件
(一)生成class文件
cmd进入
cd D:\software\JAVA\android-sdk_r24.0.2\android-sdk-windows\eclipse\workspace\DEMO1\src
javac p1.test.testdll.java
生成testdll.class
(二)生成.h文件
cd D:\software\JAVA\android-sdk_r24.0.2\android-sdk-windows\eclipse\workspace\DEMO1\src
javah -classpath D:\software\JAVA\android-sdk_r24.0.2\android-sdk-windows\eclipse\workspace\DEMO1\src p1.test.testdll
在D:\software\JAVA\android-sdk_r24.0.2\android-sdk-windows\eclipse\workspace\DEMO1\src\p1\test目录下生成testdll .h文件
或者
(1)javah -classpath D:\software\JAVA\android-sdk_r24.0.2\android-sdk-windows\eclipse\workspace\DEMO1\src -jni p1.test.testdll //在 D:\software\JAVA\android-sdk_r24.0.2\android-sdk-windows\eclipse\workspace\DEMO1\src\p1\test目录下生成testdll .h文件
(2) javah -classpath D:\software\JAVA\android-sdk_r24.0.2\android-sdk-windows\eclipse\workspace\DEMO1\src -d d:/ -jni p1.test.testdll //在D:\目录下生成testdll .h文件
3.编写C++代码
打开VC++首先新建一个Win32 Dynamic-Link library工程,之后选择An empty DLL project空工程。在这里我C++的工程是hello,把刚刚生成的那个头文件拷贝到这个工程的根目录里。
(1) 在VC工程下添加JDK的include路径
工程右键->属性->VC目录->包含目录 加入D:\Program Files (x86)\JAVA_JDK_J2SE\include 和D:\Program Files (x86)\JAVA_JDK_J2SE\include\win32
(2)新建一个C++ source file p1_test_testdll.cpp来实现这个方法。
#include"test_lily2_testdll.h"
int i = 0;
JNIEXPORT jint JNICALL Java_test_lily2_testdll_get(JNIEnv *, jclass)
{
return i;
}
JNIEXPORT void JNICALL Java_test_lily2_testdll_set(JNIEnv *, jclass, jint j)
{
i = j;
}
(3)f7编译,生成hello.dll
(4)将hello.dll放入java工程目录下D:\software\JAVA\android-sdk_r24.0.2\android-sdk-windows\eclipse\workspace\DEMO1