2

I am trying to develop a plugin for Fiji/ImageJ that relies on a native library (JNI). The JNI library itself depends on libtiff and fftw. On OSX and Linux, I use the class NativeUtils and everything works fine.

On windows, I included binary versions of libtiff and fftw in the CMake package and managed to link the JNI library against those (either statically of dynamically). However, the resulting JNI module does not include libtiff or fftw and I obtain an error when I try to load the JNI library with NativeUtils.loadLibraryFromJar. This is also the case when I include the dependent .dll in the .jar since they are not extracted by NativeUtils.

Here are the relevant lines in CMakeLists.txt:

add_library(fftw STATIC IMPORTED GLOBAL)
set_target_properties(fftw PROPERTIES IMPORTED_LOCATION "${libdir}/libfftw3f-3.lib"
                                      INTERFACE_INCLUDE_DIRECTORIES  "${incdir}")

SWIG_ADD_LIBRARY(javainterf
                 TYPE MODULE
                 LANGUAGE java
                 SOURCES javainterf.i javainterf.c src1.c)
SWIG_LINK_LIBRARIES(javainterf libcode1 fftw)

add_jar(Foo
        SOURCES ${CMAKE_CURRENT_BINARY_DIR}/java/foo1.java
        INCLUDE_JARS java/resources/ij-1.51p.jar
        VERSION ${JAR_VERSION})
add_dependencies(Foo javainterf)
add_custom_command(TARGET Foo POST_BUILD
    COMMAND "${Java_JAR_EXECUTABLE}" -uf Foo-${JAR_VERSION}.jar
    -C ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} ${JNI_LIB_NAME})

How would you make sure that all the dependencies are properly included in the jar and loaded?

hpixel
  • 260
  • 1
  • 10
  • Not a full solution, but have you read the [Developing using native libraries](https://imagej.net/Developing_using_native_libraries) page of the ImageJ documentation? Have you tried placing your native library in `$IJ_ROOT/lib/` instead of embedding within a JAR file? – ctrueden Oct 09 '17 at 15:56
  • I thought about it but it makes the install more complicated for the end user. I'll try to go with including everything in the jar works if the solution proposed by @mko works for me. – hpixel Oct 09 '17 at 19:28
  • I do not understand your concern about installation. If you use an [update site](https://imagej.net/Update_Sites) you can ship all your needed files to the user with the click of a button on their end, and they'll receive updates automatically, too. – ctrueden Oct 31 '17 at 18:00
  • @ctrueden I just didn't know about this. I'll try it. Thanks – hpixel Oct 31 '17 at 21:32

1 Answers1

1

You can't load library from inside JAR without extracting it in a first place.

Take a look here at full sample where native code is embedded inside JAR and extracted when needed.

https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo031

Update

Well, in that case, when you need to pack more libs and you want to properly resolve locations, you need to play with runtime env a little bit.

Take a look here:

https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo035

git clone https://github.com/mkowsiak/jnicookbook
cd jnicookbook/recipes/recipeNo035
make
make test

Have fun with JNI!

Oo.oO
  • 12,464
  • 3
  • 23
  • 45
  • The problem here is that I have several dependent libraries and only one get extracted at a time. I don't see how to merge all the dependencies into one dll with cmake. – hpixel Oct 06 '17 at 19:14
  • You can always extract all the libraries and load all of them using System.load. After all, it's just all about symbols that are loaded from libs. – Oo.oO Oct 06 '17 at 20:02
  • My jni library depends on some non-jni shared libraries. Even though they are not jni, I tried to load them with `loadlibraryfromjar`, and it does not work: I get the very same error. – hpixel Oct 06 '17 at 21:16
  • I haven't have time to test your solution yet. But thanks for taking the time to write an additional recipe for me. I'll accept your answer as soon as I have a chance to test it. Thanks – hpixel Oct 31 '17 at 21:35
  • 1
    > "You can't load library from inside JAR without extracting it in a first place." what do you mean by this ? I just put my DLL in the .jar and it works fine (with JNA) – Jean-Michaël Celerier Sep 06 '18 at 22:35
  • com/sun/jna/Native.java -> extractFromResourcePath – Oo.oO Sep 07 '18 at 13:09
  • You can load library from inside jar – Valentin May 11 '20 at 00:40