GNU/Linux >> Linux Esercitazione >  >> Linux

Come compilare una libreria dinamica per un'applicazione JNI su Linux?

La libreria nativa può essere caricata da loadLibrary con un nome valido. Ad esempio, libXXXX .so per la famiglia linux, il tuo hellolib.so dovrebbe essere rinominato in libhello.so. A proposito, sviluppo java con jni, separerò l'implementazione e l'interfaccia nativa (.c o .cpp).

static {
    System.loadLibrary("hello"); // will load libhello.so
}

L'intestazione dell'implementazione (HelloImpl.h):

#ifndef _HELLO_IMPL_H
#define _HELLO_IMPL_H

#ifdef __cplusplus
        extern "C" {
#endif

        void sayHello ();

#ifdef __cplusplus
        }
#endif

#endif

HelloImpl.cpp:

#include "HelloImpl.h"
#include  <iostream>

using namespace std;

void sayHello () {
    cout << "Hello World!" << endl;
    return;
}

Hello.c (preferisco compilare jni in c):

#include <jni.h>
#include "Hello.h"
#include "HelloImpl.h"

JNIEXPORT void JNICALL Java_Hello_sayHello (JNIEnv *env, jobject obj) {
    sayHello();
    return;
}

Infine, possiamo compilarli in alcuni passaggi:

  1. compila obj (genera HelloImpl.o)

g++ -c -I"/opt/java/include"-I"/opt/java/include/linux" HelloImpl.cpp

  1. compilare jni con .o

g++ -I"/opt/java/include"-I"/opt/java/include/linux" -o libhello.so -shared-Wl,-soname,hello.so Hello.c HelloImpl.o -static -lc

nel passaggio 2, usiamo g++ per compilarlo. Questo è molto importante. Puoi vedere Come mescolare C e C++

Dopo la compilazione, puoi controllare la denominazione della funzione con nm:

$ nm libhello.so |grep say
00000708 T Java_Hello_sayHello
00000784 t _GLOBAL__I_sayHello
00000718 T sayHello

C'è un Java_Hello_sayHello contrassegnato con T. Dovrebbe essere esattamente uguale al nome del tuo metodo nativo. Se è tutto ok. puoi eseguirlo:

$ java -Djava.library.path=. Hello
Hello World!

Finalmente il mio codice funziona. Questo è hello.java

public class hello {
  public native void sayHello(int length) ;
  public static void main (String args[]) {
    String str = "I am a good boy" ;
    hello h = new hello () ;
    h.sayHello (str.length() ) ;
  }
  static {
    System.loadLibrary ( "hello" ) ;
  }
}

Dovresti compilarlo come :

$ javac hello.java 

Per creare un file .h devi eseguire questo comando:

$ javah -jni hello

Questo è hello.h :

JNIEXPORT void JNICALL Java_hello_sayHello
(JNIEnv *, jobject, jint);

Ecco hello.c :

#include<stdio.h>
#include<jni.h>
#include "hello.h" 

JNIEXPORT void JNICALL Java_hello_sayHello
  (JNIEnv *env, jobject object, jint len) {
  printf ( "\nLength is %d", len ); }

Per compilare questo e creare una libreria condivisa dobbiamo eseguire questo comando :

$ gcc -I/usr/lib/jvm/java-6-openjdk/include -o libhello.so -shared hello.c

Poi finalmente esegui questo :

$ java -Djava.library.path=. hello

Questo lamenta che i simboli C++ non sono disponibili. Mi sembra di ricordare, quando facevo cose JNI tutto il tempo che c'erano problemi di collegamento nelle librerie C++ e ci siamo sempre attenuti al semplice vecchio C

Se modifichi il tuo codice in modo che sia C standard (e rinomini il file):

#include <jni.h>
#include "Hello.h"
#include <stdio.h>

JNIEXPORT void JNICALL Java_Hello_sayHello (JNIEnv *env, jobject obj) {
        printf("Hello World");
        return;
}

E compilalo

gcc -I/usr/lib/jvm/java-6-openjdk/include  -o libhellolib.so -shared Hello.c

Funziona

java -Djava.library.path=`pwd` Hello
Hello World

Linux
  1. Come gestire le librerie dinamiche e statiche in Linux

  2. Come trovare l'applicazione per un tipo Mime su Linux?

  3. Libreria condivisa dinamica C++ su Linux

  4. Come inizializzare una libreria condivisa su Linux

  5. Come configurare googleTest come libreria condivisa su Linux

Come configurare Openbox per il tuo desktop Linux

Come controllare (scansionare) le porte aperte in Linux

Come configurare un cluster Pacemaker per Linux ad alta disponibilità

Come installare la libreria Python PyBrain in Linux

Come installare Setuptools per Python su Linux

Come compilare l'app .NET Core per Linux in un computer Windows