linuxでjavaがjniを介してsoダイナミックライブラリを呼び出す方法


プロジェクトではsoダイナミックライブラリのメソッドを呼び出して必要な機能を実現する必要があるため、javaプロジェクトではjni方式で呼び出しを実現する必要がある.
今回の学習記録に対応するシーンは次のとおりです.
  • には、soライブラリおよび対応するメソッドのヘッダファイルが既に提供されている.
  • プロジェクトが提供するsoとヘッダファイルはjniのヘッダファイルではないので、自分で提供したヘッダファイルを通じてjniメソッドを作成し、1つのsoファイルを再コンパイルし、2つのsoを同時にロードする必要があります.(最初は接触したばかりで、ソースコードがない場合に2つのsoを1つのsoにコンパイルして統合できるかどうか分かりません.これで2つをロードする必要はありませんが、この考えはまだ理解されていません.)
  •  
    1.gccコンパイラがインストールされていることを確認する.FileUtilを作成します.JAvaコードは、nativeでcで実現する必要がある関数を宣言します.ソースプログラムがパッケージに含まれている場合、com/hnrbyl/rmas/util/FileUtilのような同じフォルダ構造を構築するべきである.java
    Javaコード
    
      
    public class FileUtil {  
        public native static String ResultText();   
        public static void main(String[] args) {  
            System.loadLibrary("FileUtil");  
            String s=FileUtil.ResultText();  
            System.out.println(s);  
        }  
      
    }  
    

    プロジェクト内のコード:
    Javaコード
    public class FileUtil {    
            //   .so        
        public native static String ResultText(String txtPath, String pdfPath);     
        
        public static String autoAnalyse(String txtPath, String pdfPath){    
            //                        
            System.loadLibrary("FileUtil");    
            String jsonData = FileUtil.ResultText(txtPath, pdfPath);    
            return jsonData;    
        }    
    }   

    3.FileUtil.JAvaファイルが存在するディレクトリの下でコンパイルする.JAvaファイルJavac FileUtil.java 4. 第3ステップで生成する.classファイルは、対応するものを生成する.hヘッダファイル、本例ではcom_を生成するhnrbyl_rmas_util_FileUtil Javah –classpath  ~workspace\elect\WebRoot\WEB-INF\classes -d d:\-jni com.hnrbyl.rmas.util.FileUtil java内の各コマンドの意味-classpathクラスに移行するパス-d出力ディレクトリ-jni JNIスタイルのヘッダファイルを生成するために使用されます(デフォルト)このJavaファイルはパス「E:workspaceelectsrc」の下でパッケージ「package com.hnrbyl.rmas.util;で得られたFileUtil対応のclassファイルは、パス「E:workspaceelectWebRootWEB-INFclassescomhnrbylrmasutil」の下にあります.以上のコマンドで指定するパスに注意してください.コマンドの実行位置がソースディレクトリであることに注意してください.E:workspaceelectsrc"-classpathの後ろのパスはパッケージです.com.hnrbyl.rmas.utilが存在するルート
     
    5.第4部で生成したヘッダファイルの内容
    Cコード
    /* DO NOT EDIT THIS FILE - it is machine generated */  
    #include "jni.h"  
    /* Header for class FileUtil */  
      
    #ifndef _Included_com_hnrbyl_rmas_util_FileUtil  
    #define _Included_com_hnrbyl_rmas_util_FileUtil  
    #ifdef __cplusplus  
    extern "C" {  
    #endif  
    /* 
     * Class:     com_hnrbyl_rmas_util_FileUtil 
     * Method:    ResultText 
     * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 
     */  
    JNIEXPORT jstring JNICALL Java_com_hnrbyl_rmas_util_FileUtil_ResultText  
      (JNIEnv *, jclass, jstring, jstring);  
      
      
    #ifdef __cplusplus  
    }  
    #endif  
    #endif  

    6.FileUtilを作成する.cファイルは、参照ステップ4で生成する.hヘッダファイルを宣言し、そのメソッドを宣言します.
    #include "stdlib.h"  
    #include "stdio.h"  
    #include "FileUtil.h"  
    #include "dlfcn.h"  
    #include "jni.h"  
    JNIEXPORT jstring JNICALL  Java_com_hnrbyl_rmas_util_FileUtil_ResultText  
      (JNIEnv *env, jobject obj, jstring txtPath, jstring pdfPath)   
        {  
           char** (*myso)(char* a, char* b);//function pointer     
           void *handle;   
           char *errorInfo;  
           handle=dlopen("libauto_analyse.so",RTLD_LAZY);//open lib file     
           errorInfo = dlerror();  
           //      NULL   ,          ,    。    ,           ,           
           if (errorInfo){  
               //      NULL   ,  dlerror                 
               printf("Open Error:%s.
    ",dlerror()); return 0; } // dlsym , 。 , NULL myso=dlsym(handle,"auto_analyse");//call dlsym function errorInfo = dlerror();// dlerror , , if (errorInfo){ printf("Dlsym Error:%s.
    ",errorInfo); return 1; } char* a=(*env)->GetStringUTFChars(env, txtPath, 0); char* b=(*env)->GetStringUTFChars(env, pdfPath, 0); char **str=(*myso)(a,b); dlclose(handle); (*env)->ReleaseStringUTFChars(env, txtPath, a); (*env)->ReleaseStringUTFChars(env, pdfPath, b); jstring rtn; rtn = (*env)->NewStringUTF(env,str[1]); return rtn; }

     
    7.第6ステップで作成したFileUtilについて述べる.cファイル、コンパイル.soファイル
    gcc -I/wenjin/jdk1.7.0_25/include/-I/wenjin/jdk1.7.0_25/include/linux/-fPIC -shared -o libFileUtil.so FileUtil.c  -L. -lefsapi -Wl,-rpath,.
    注:/wenjin/jdk 1.7.0_25/includeはjniです.hヘッダファイルが存在するパス
    /wenjin/jdk1.7.0_25/include/linuxはjni_md.hが存在する経路
    -L.現在のディレクトリでは、プロジェクトにリンクするsoライブラリファイル、すなわちsoが使用する別のsoを作成する必要があります.コンパイル時に指定する必要があります.
    GCC共通パラメータの詳細:https://www.cnblogs.com/zhangsir6/articles/2956798.html8.ステップ7で生成するlibFileUtil.soファイルjavaのロードライブラリLD_にコピーLIBRARY_PATHが指す経路の中.
    9.システムを通過する.loadlibraryはsoをロードし、関数を呼び出します.