How to call external dll function from java code

我的梦境 提交于 2019-11-28 00:05:20

I stumbled upon the same problem of "calling DLL from Java" and first was frustrated about the complexity. Yet, there is an elegant solution (might also be interesting for the people over there in the processing.org habitat..) Given the rather "general" form of the question (maybe, downrating is not justified for that), I suppose, a rather easy-going solution would be indicated. In other words, a solution that avoids messing aronud with header files, extra conversions, etc., just as the source code is not necessarily available.

My recommendation for that would be JNA (https://github.com/twall/jna), which basically is a simplifying wrapper around JNI. It works great, type mapping is straightforward (e.g. pchar = lpcstr buffer -> string), though I am using it only towards Windows DLLs and my own C-style DLLs created using Delphi-Pascal. The only thing to consider is that return values should be exported through functions rather than "out" flagged reference variables. The question already points to a linked source that provides an example for that (so, answers around JNI may be misplaced here). Note that the link I provided also contains axamples for the transfer of arrays and pointers.

You will need to use the Java Native Interface (JNI), which is a set of C/C++ functions that allow native code to interface with java code (i.e. receiving parameters from java function calls, returning results, etc). Write a wrapper C library that receive JNI calls and then call your external library.

For instance, the following function invokes a method updateHandlers on a native object (that is stored as long in the Java side).

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);
}

The corresponding declarations in package.ClassName are:

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
}

I did write some time ago sample tutorial, maybe it will help.

http://wendro.blogspot.com/2010/03/jni-example-eclipse-dev-cpp.html

You declare your native functions in java (native private ...) with the signature that you need; then run javah (a tool that is provided with the JDK) in order to generate the native headers. A List<String> (actually a List, because of type erasure) is a jobject in native code.

The corresponding C method, would be:

JNIEXPORT jobject JNICALL package_Classname_getWords(JNIEnv *env, jobject jobj, jstring word)

I think it would be easier to return an array of strings jobjectArray, and instantiate the List in java from the returned values. See this example.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!