How to call a c/c++ shared lib from java

You have two ways at here, JNI and JNA. JNA is based on JNI, but simpler at usage here. I will give an example for JNA usage today. It does not need use javah to create a header file.

  1. Add jna lib to you maven :
    <dependency>
    
     <groupId>net.java.dev.jna</groupId>
    
     <artifactId>jna</artifactId>
    
     <version>4.4.0</version>
    
     </dependency>
  2. Create a c file like this:
    cd /home/test
    
    touch MyTest.c
    /* MyTest.c */
    #include <stdio.h>
    
    void aSimplePrint() {
     printf("Hello world from C!\n");
    }
  3. compile the c file to the .so share lib file:
    gcc -c -fPIC MyTest.c -o MyTest.o
    gcc -shared -o libMyTest.so MyTest.o
  4. Create a java file like this, TestJNA.java
    import com.sun.jna.Library;
    import com.sun.jna.Native;
    
    public class TestJNA {
    
        static {
            System.setProperty("jna.library.path", "/home/test");
      }
    
        public interface MyTest extends Library {
            public void aSimplePrint();
         }
    
        public static void main(String[] args) {
            MyTest ctest = (MyTest) Native.loadLibrary("MyTest", MyTest.class);
            ctest.aSimplePrint();
         }
    }

    Compile to get the TestJNA.class.

  5. Then you can run the java main to test it:
    java -cp .:/path/to/jna-4.4.0.jar TestJNA

The whole process will be like this. And you could face some issue if lib is 3rd party one or others reason.
Here are some issues you may encounter in the process.

1. In linux, loadLibrary(“MyTest” will point to load a libMyTest.so file. You need pay attention name of lib at here.

2. “Exception in thread “main” java.lang.UnsatisfiedLinkError: no MyTest in java.library.path ……..”
This means java can not find the libMyTest.so in the lib folder.  This code is to solve that problem.
System.setProperty(“jna.library.path”, “/home/test”);
If you still have issue, you can try this code too:
System.load(“/home/test/libMyTest.so”);

3. If you can load lib, but can not find symbol or function name in the lib:
Exception in thread “main” java.lang.UnsatisfiedLinkError: Error looking up function ‘aSimplePrint’: /home/test/libMyTest.so: undefined symbol: …………………

Then use this command to check what a share lib .so contains in the API:
nm -D /home/test/libMyTest.so
By this way, you can know that (T) function is existing in the lib or not.

4. Command :
file /home/test/libMyTest.so
— will tell you info about this file include it is for 32bit or 64 bit will will cause some problem of some 3rd party lib files.

Advertisements