我需要从 Java 代码中调用外部 DLL 库函数。我使用 Netbeans 7.2。我的dll的功能是:
Boolean isValid(string word)
List<String> getWords(String word)
我偶然发现了“从 Java 调用 DLL”的相同问题,并且首先对复杂性感到沮丧。然而,有一个优雅的解决方案(对于 processing.org 栖息地的人们来说可能也很有趣..)鉴于问题的相当“一般”形式(也许,降级是不合理的),我想,将提出一个相当容易的解决方案。换句话说,一种避免与头文件、额外转换等混淆的解决方案,就像源代码不一定可用一样。
我的建议是 JNA(https://github.com/twall/jna),它基本上是 JNI 的简化包装器。它工作得很好,类型映射很简单(例如 pchar = lpcstr 缓冲区 -> 字符串),尽管我只将它用于 Windows DLL 和我自己使用 Delphi-Pascal 创建的 C 样式 DLL。唯一需要考虑的是返回值应该通过函数而不是“out”标记的引用变量导出。该问题已经指向一个提供示例的链接源(因此,围绕 JNI 的答案可能在这里放错了地方)。请注意,我提供的链接还包含用于传输数组和指针的示例。
您将需要使用Java 本地接口 (JNI),它是一组 C/C++ 函数,允许本地代码与 java 代码交互(即从 java 函数调用接收参数、返回结果等)。编写一个接收 JNI 调用的包装 C 库,然后调用您的外部库。
例如,以下函数调用updateHandlers
本机对象(存储在 Java 端中的长度)上的方法。
class MyImpl {
void updateHandlers(JNIEnv *env) {
this->contentHandler = ....;
}
}
JNIEXPORT void JNICALL Java_package_Classname_updateHandlers0
(JNIEnv *env, jobject obj, jlong ptr)
{
((MyImpl*)ptr)->updateHandlers(env);
}
package.ClassName 中对应的声明是:
private long ptr; //assigned from JNI
public void updateHandlers() {
if (ptr==0) throw new NullPointerException();
updateHandlers0(ptr);
}
private native void updateHandlers0(long ptr);
static {
try {
/*try preloading the library external.dll*/
System.loadLibrary("external");
} catch (UnsatisfiedLinkError e) {
/*library will be resolved when loading myjni*/
}
System.loadLibrary("myjni"); //load myjni.dll
}
native private ...
你用你需要的签名在 java() 中声明你的本地函数;然后运行javah
(JDK 随附的工具)以生成本机标头。A List<String>
(实际上是 a List
,因为类型擦除)jobject
在本机代码中是 a 。
相应的 C 方法将是:
JNIEXPORT jobject JNICALL package_Classname_getWords(JNIEnv *env, jobject jobj, jstring word)
我认为返回一个字符串数组会更容易jobjectArray
,并从返回的值中实例化 java 中的 List 。请参阅此示例。
我前段时间确实写过示例教程,也许它会有所帮助。
http://wendro.blogspot.com/2010/03/jni-example-eclipse-dev-cpp.html