{"id":2271,"date":"2011-01-20T11:30:12","date_gmt":"2011-01-20T09:30:12","guid":{"rendered":"https:\/\/test.viaboxx.de\/2011\/01\/20\/java-interoperation-with-a-native-dll-using-jna\/"},"modified":"2021-08-11T10:09:51","modified_gmt":"2021-08-11T10:09:51","slug":"java-interoperation-with-a-native-dll-using-jna","status":"publish","type":"post","link":"https:\/\/www.viaboxx.de\/en\/blog\/java-interoperation-with-a-native-dll-using-jna\/","title":{"rendered":"Java interoperation with a Native DLL using JNA"},"content":{"rendered":"\n<p>Imagine you get a static link library (.lib file) whose functions need to be invoked from a Java application. You cannot link the library to your java program, but what you can do is to call functions from a dynamic link library (DLL).<\/p>\n\n\n\n<p>The term \u201cDLL\u201d does not imply a specific format and thus the tooling you should use from Java to call the functions depends on what kind of DLL it is. It could be a .NET library that contains managed code or it could be a native dll with unmanged code (both concerns the Windows platform).<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><a href=\"http:\/\/www.viaboxx.de\/wp-content\/uploads\/2014\/06\/lib-dll-java.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"269\" height=\"303\" src=\"http:\/\/www.viaboxx.de\/wp-content\/uploads\/2014\/06\/lib-dll-java.jpg\" alt=\"lib-dll-java\" class=\"wp-image-2272\" srcset=\"https:\/\/www.viaboxx.de\/wp-content\/uploads\/2014\/06\/lib-dll-java.jpg 269w, https:\/\/www.viaboxx.de\/wp-content\/uploads\/2014\/06\/lib-dll-java-266x300.jpg 266w\" sizes=\"(max-width: 269px) 100vw, 269px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>This blog post is about the interoperation of Java with a native DLL. It could have been created with <a href=\"http:\/\/www.microsoft.com\/express\/Windows\/\">Microsoft Visual Studio C++<\/a>. The DLL links the static link library and is a \u201cMulti-threaded DLL\u201d with \u201cNo Common Language Runtime support\u201d.<\/p>\n\n\n\n<p>From the Java side, you have the choice between <a href=\"http:\/\/en.wikipedia.org\/wiki\/Java_Native_Interface\">Java Native Interface (JNI)<\/a> and <a href=\"http:\/\/en.wikipedia.org\/wiki\/Java_Native_Access\">Java Native Access (JNA)<\/a>.<\/p>\n\n\n\n<p>The usual low-level way is to use JNI to access the DLL, but this is much more error-prone and less productive than using JNA.<\/p>\n\n\n\n<p>The JNA framework consists of a single jna.jar and can be downloaded here: <a title=\"Java Native Access (JNA) \" href=\"https:\/\/jna.dev.java.net\/\" target=\"_blank\" rel=\"noopener\">Java Native Access (JNA) \u2013 downloads and documentation<\/a>. If you use maven to build the project, just add the dependency:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted notranslate\">&nbsp;\n   net.java.dev.jna\n   jna\n   3.2.7\n   compile\n<\/pre>\n\n\n\n<p>You basically create a Java interface to wrap the DLL functions to be invoked, but\u2026<\/p>\n\n\n\n<p>Here are some technical details of interesting integration problems, depending on the signature of the DLL functions, that need to be invoked:<\/p>\n\n\n\n<p class=\"has-normal-font-size\"><strong>Consider the calling convention<\/strong><\/p>\n\n\n\n<p>Depending on the <a href=\"http:\/\/en.wikipedia.org\/wiki\/X86_calling_conventions\" target=\"_blank\" rel=\"noopener\">calling convention<\/a> that the DLL expects, the wrapper interface needs to inherit from \u201ccom.sun.jna.Library\u201d or \u201ccom.sun.jna.win32.StdCallLibrary\u201d.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted notranslate\">C++:\n#define EXAMPLE_DLL extern \"C\" __declspec(dllexport)\nEXAMPLE_DLL char* returnDLLVersion();<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted notranslate\">Java:\npublic interface ExampleDLL extends Library {\n  ExampleDLL INSTANCE = (ExampleDLL) Native.loadLibrary(\"example.dll\", ExampleDLL.class);\n &nbsp;String returnDLLVersion();\n}<\/pre>\n\n\n\n<p>The Microsoft-specific directive __declspec(dllexport) exports the functions for the DLL so that a client can invoke them. Usually, you create a macro definition: <strong>#define EXAMPLE_DLL<\/strong> to make the code more readable.<\/p>\n\n\n\n<p class=\"has-normal-font-size\"><strong>Data type mapping between C and Java<\/strong><\/p>\n\n\n\n<p>The function \u201creturnDLLVersion\u201d returns a char pointer (C-String). The JNA-framework converts this to a Java String (Unicode). It offers automatic conversions for most C-data types to\/from Java. Detailed documentation is here: \u201c<a href=\"https:\/\/jna.dev.java.net\/#mapping\" rel=\"nofollow\">Mapping between Java and Native<\/a>\u201c.<\/p>\n\n\n\n<p class=\"has-normal-font-size\"><strong>Writing output into shared memory<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted notranslate\">C++:\nEXAMPLE_DLL bool readBufferContent(unsigned char* outbuf);\n\nJava:\nboolean readBufferContent(Memory memory);<\/pre>\n\n\n\n<p>The C-function \u201creadBufferContent()\u201d writes an output string into memory, that Java needs to provide and read. If the maximum output length is known before, you can use this procedure:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Java reserves a fixed amount of bytes:<br>Memory memory = new Memory(100);<\/li><li>Java passes a pointer to the memory to the DLL:<br>ExampleDLL.INSTANCE.readBufferContent(memory);<\/li><li>C++ writes the String and the DLL call returns.<\/li><li>Java reads the memory content and creates a String object with:<br>String bufferContent = memory.getString(0);<\/li><li>The Java Garbage Collector cares about freeing the Memory-Object (somewhen), as soon as there are no references to it. What a luxury!<\/li><\/ol>\n\n\n\n<p class=\"has-normal-font-size\"><strong>An output parameter of type \u201cint\u201d: call-by-reference<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted notranslate\">C++:\nEXAMPLE_DLL ResultStruct* consolidate(const short *cardTypes, int *numberOfResults);\n\nJava:\nPointer consolidate(int[] cardTypes, IntByReference numberOfResults);<\/pre>\n\n\n\n<p>The consolidate()-function demonstrates multiple problems:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>First parameter is an int-Array. In C, you pass a pointer to the array. Fortunately, JNA automatically converts primitive arrays, see JNA-documentation chapter \u201c<a rel=\"nofollow\" href=\"https:\/\/jna.dev.java.net\/#pointers\">Pointers and Arrays<\/a>\u201c.<\/li><li>The second parameter is an \u201cout\u201d-parameter. The DLL puts the number of results into the variable \u201cnumberOfResults\u201d. It is used to determine the length of the array that the function returns. Thus, you need to pass the int-variable by reference. JNA provides various ByReference-classes, e.g. \u201ccom.sun.jna.ptr.IntByReference\u201d.<br>Java can get the int-value after the call with:<br>int value = numberResults.getValue();<\/li><li>The return value of the function is an array of dynamic length. Instead of using the IntByReference parameter, it could have been possible to determine the array length by terminating the array with a NULL-element. This implementation decision has not been taken here, thus the array-length is determined by the value of the 2nd parameter \u201cnumberOfResults\u201d, so that the Java program does not need to compute it dynamically.<\/li><\/ol>\n\n\n\n<p class=\"has-normal-font-size\"><strong>Dynamic memory reserved in the DLL: return an array of struct of dynamic length<\/strong><\/p>\n\n\n\n<p>The array elements are C-structs of type \u201cResultStruct\u201d. Unfortunately, JNA cannot automatically convert an array of structs. It can convert a single struct into a Java object and arrays of primitives, so here the conversion must be implemented ourselves.<\/p>\n\n\n\n<p>There are two questions:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>How to allocate and free the dynamic memory for the result array of structs? (To avoid a memory leak!)<\/li><li>How to create the Java objects?<\/li><\/ol>\n\n\n\n<p>The length and thus the amount of memory is unknown before the function call, so we decide not to use a fixed-length Memory object of JNA. Instead, the DLL dynamically reserves memory, but we must pay attention to the scope so that the memory is still allocated when the function-call returns. The C++ program can use \u201cmalloc()\u201d or \u201cnew\u201d to allocate heap memory. To free it correctly, the DLL provides a separate freeMemory() function:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted notranslate\">C++:\nvoid freeMemory(ResultStruct *arr) { if(arr) delete[] arr; }\n\nJava:\nvoid freeMemory(Pointer p);<\/pre>\n\n\n\n<p>The Java program cannot free the memory itself, because the DLL uses a separate heap manager. You can find a discussion of this issue here: <a href=\"http:\/\/www.codeguru.com\/forum\/archive\/index.php\/t-62114.html\">in a C++ forum<\/a><\/p>\n\n\n\n<p class=\"has-normal-font-size\"><strong>Create Java objects from an array of C-structs<\/strong><\/p>\n\n\n\n<p>We map the return type of the function as a com.sun.jna.Pointer in Java. With the knowledge about the C-struct (sequence and data type of member variables), the java program can read and convert the memory content to create adequate objects. The number of elements in the array is also known (variable \u201cnumberOfResults\u201d, see above). It is very important, to compute the offset correctly to avoid JVM-crashes for invalid memory access!<\/p>\n\n\n\n<pre class=\"wp-block-preformatted notranslate\">C++:\nstruct ResultStruct {\n&nbsp; unsigned short count;\n  char description[40];\n&nbsp; unsigned short average;\n};\n\nJava:\npublic static class ResultStruct {\n&nbsp; public short count;\n&nbsp; public String description;\n&nbsp; public short average;\n}\n\nstatic ResultStruct[] fromArrayPointer(Pointer pointer, int numberResults) {\n  ResultStruct[] arr = new ResultStruct[numberResults];\n  int offset = 0;\n  for (int i = 0; i &lt; numberResults; i++) {\n    arr[i] = fromPointer(pointer, offset);\n    offset += 44;\n  }\n  return arr;\n }\n\nstatic ResultStruct fromPointer(Pointer pointer, int offset) {\n&nbsp; ResultStruct inst = new ResultStruct();\n&nbsp; inst.count = pointer.getShort(offset);\n&nbsp; offset += 2;\n&nbsp; inst.description = pointer.getString(offset);\n&nbsp; offset += 40;\n&nbsp; inst.average = pointer.getShort(offset);\n&nbsp; return inst;\n}<\/pre>\n\n\n\n<p class=\"has-normal-font-size\"><strong>Callback functions (Call a Java method from within the C++ DLL)<\/strong><\/p>\n\n\n\n<p>In places, where C gets a function pointer to call a function, this can be used to call Java methods as well. JNA offers a Callback-interface, documented in the chapter \u201c<a rel=\"nofollow\" href=\"https:\/\/jna.dev.java.net\/#callbacks\">Callbacks\/Closures<\/a>\u201c. The Callback class inherits form the Callback interface and contains a single method of arbitrary name and compatible signature.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted notranslate\">C++:\nEXAMPLE_DLL void setFunction(void (*func)(char **texts, int count));\n\nJava:\nvoid setFunction(ExampleCallback callback);\n\npublic interface ExampleCallback extends Callback {\n    void receive(Pointer pointerToTexts, int count);\n}<\/pre>\n\n\n\n<p class=\"has-normal-font-size\"><strong>Convert a char** into a String-array<\/strong><\/p>\n\n\n\n<p>Finally, a look at the signature of the \u201creceive\u201d method in the ExampleCallback interface. It gets a string array in form of\u00a0a pointer to a pointer, char **. Because of the differences between C-strings and Java-strings, you should use the method Pointer.getStringArray(int, int) provided by JNA to do the conversion. No care needs to be taken of memory usage, because the memory for the strings has been allocated by the C-DLL and the call happens from inside the DLL, so the C-program is responsible to free the memory when the callback returns. The java-strings copy the memory content and are completely decoupled from the c-strings.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted notranslate\">public void receive(Pointer pointerToTexts, int count) {\n  String[] texts = pointerToTexts.getStringArray(0, count);\n  ...\n}<\/pre>\n\n\n\n<p>We hope that the barrier to leave the Java world, through these examples, is diminished!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Imagine you get a static link library (.lib file) whose functions need to be invoked from a Java application. You cannot link the library to your [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":"","site-sidebar-layout":"default","site-content-layout":"default","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"default","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[76],"tags":[],"class_list":["post-2271","post","type-post","status-publish","format-standard","hentry","category-code"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"Simon Tiffert","author_link":"https:\/\/www.viaboxx.de\/en\/blog\/author\/simon-tiffertviaboxx-de\/"},"uagb_comment_info":0,"uagb_excerpt":"Imagine you get a static link library (.lib file) whose functions need to be invoked from a Java application. You cannot link the library to your [&hellip;]","_links":{"self":[{"href":"https:\/\/www.viaboxx.de\/en\/wp-json\/wp\/v2\/posts\/2271"}],"collection":[{"href":"https:\/\/www.viaboxx.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.viaboxx.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.viaboxx.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.viaboxx.de\/en\/wp-json\/wp\/v2\/comments?post=2271"}],"version-history":[{"count":2,"href":"https:\/\/www.viaboxx.de\/en\/wp-json\/wp\/v2\/posts\/2271\/revisions"}],"predecessor-version":[{"id":7066,"href":"https:\/\/www.viaboxx.de\/en\/wp-json\/wp\/v2\/posts\/2271\/revisions\/7066"}],"wp:attachment":[{"href":"https:\/\/www.viaboxx.de\/en\/wp-json\/wp\/v2\/media?parent=2271"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.viaboxx.de\/en\/wp-json\/wp\/v2\/categories?post=2271"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.viaboxx.de\/en\/wp-json\/wp\/v2\/tags?post=2271"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}