一 、封裝動态庫
java調用linux動态庫有兩種方式:(Windows為.dll 方式類似)
jni:性能較jna更優,但文檔較少不易上手,且java開發人員實作jni需要寫c代碼(輸入輸出參數複雜時轉換很麻煩)
jna:是基于JNI的,在JNI上封裝了一層,故JNA性能不如JNI,但java通過jna調用動态庫時不需要寫c代碼,參數轉換由架構 實作。
以下動态庫實作參考: https://blog.csdn.net/guowenyan001/article/details/50353214
1.1 說明
rk4.h、rk4.c是生成庫的代碼。//未完全版,但參數傳遞的方式都已驗證通過
1.2 代碼
rk4.h
#ifndef RK4_H_
#define RK4_H_
#define MAX_TAP_POINT 19
#define MAX_YY_INDEX 1024
//定義輸入基本資料結構體
typedef struct
{
float m_oil, m_wd;
int n_fan, n_fanwork;
float R_H[MAX_TAP_POINT][3], R_M[MAX_TAP_POINT][3], R_Ld[3];//二維數組 一維數組
}Tran_info;
//定義輸入實時資料結構體
typedef struct
{
float U, i_H, i_M, i_L;
int T_now;
}Time_info;
//定義輸出實時資料結構體
typedef struct
{
float tmp1, tmp2, tmp3, min;
float load_min[11];
}data_out;
extern Tran_info transinfo;
extern Time_info measureinfo;
extern void monitor(Tran_info *info1,Time_info *info2,data_out *data);
#endif
rk4.c
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "rk4.h"
Tran_info transinfo;
Time_info measureinfo;
void monitor(Tran_info *info1,Time_info *info2,data_out *data)
{//隻做輸出輸入的參數及傳回參數
memcpy((unsigned char*)&transinfo,(unsigned char*) info1,sizeof(transinfo));
printf("transinfo.n_fan=%.4f\n", transinfo.n_fan);
printf("R_H00=%.4f,R_H00[0][2]=%.4f,R_H11=%.4f\n", transinfo.R_H[0][0],transinfo.R_H[0][2],transinfo.R_H[1][1]);
memcpy((unsigned char*)&measureinfo,(unsigned char*) info2,sizeof(measureinfo));
printf("U=%.4f,T_now=%.4d\n", measureinfo.U,measureinfo.T_now);
printf("tmp1=%.4f,tmp2=%.4f,tmp3=%.4f,min=%.4f\n", data->tmp1,data->tmp2,data->tmp3,data->min);
printf("%.4f %.4f %.4f\n", data->load_min[0],data->load_min[3],data->load_min[9]);
return ;
}
1.3 生成動态庫
生成rk4.o:
gcc -c -fPIC rk4.c -lm (注意:若.c檔案引入了#include <math.h> 需要在後面加 -lm)
生成動态庫libmyrk4.so:
gcc -shared -fPIC -o libmyrk4.so rk4.o -lm (若引入#include <math.h> 加 -lm 不然調用math庫時會找不到該實作)
1.4 動态連結庫所在路徑加入配置檔案中
$ gcc -fpic -shared -o libmyrk4.so rk4.c (切換到root使用者下)
$ pwd >> /etc/ld.so.conf (把動态連結庫所在路徑加入配置檔案中,此處用pwd是因為筆者 目前所在目錄就是連結庫檔案所在目錄)
$ ldconfig
二 java調用類
package cn.fast_arithmetic.calc;
import java.util.Arrays;
import com.calc.api.TieeInputParams;
import com.calc.api.TieeOutput;
import com.sun.jna.Library;//需要下載下傳引入jna包
import com.sun.jna.Native;
import com.sun.jna.Structure;
public class Algorithm {
public interface TieeLibrary extends Library {
TieeLibrary INSTANCE = (TieeLibrary) Native.loadLibrary("myrk4", TieeLibrary.class);//myrk4 為生成的libmyrk4.so
public static class Tran_info extends Structure {
public float m_oil;//結構體參數類型及順序要嚴格按照C結構體的類型及順序
public float m_wd;
public float[] R_H = new float[57];//結構體二維數組float[19][3]需要定義為一維數組
public float[] R_M = new float[57];
public float[] R_Ld = new float[3];
public static class ByReference extends Tran_info implements Structure.ByReference {
//指針和引用的傳遞使用ByReference
}
public static class ByValue extends Tran_info implements Structure.ByValue {
//拷貝參數傳遞使用ByValue
}
//@Override
//public String toString() {
//可通過toString列印結構體的值
//}
}
public static class Time_info extends Structure {
public float U;
public float i_H;
public float i_M;
public float i_L;
public int T_now;
public static class ByReference extends Time_info implements Structure.ByReference {
}
public static class ByValue extends Time_info implements Structure.ByValue {
}
}
public static class data_out extends Structure {
public float tmp1;
public float tmp2;
public float tmp3;
public float min;
public float[] load_min = new float[11];
public static class ByReference extends data_out implements Structure.ByReference {
}
public static class ByValue extends data_out implements Structure.ByValue {
}
}
void monitor(Tran_info.ByReference tran_info, Time_info.ByReference time_info, data_out.ByReference dataout);
}
//函數調用方式
public static CalcOutput processCalc(CalcInputParams params) throws Exception {
CalcOutput out = new CalcOutput ();
TieeLibrary.Tran_info.ByReference info1 = new TieeLibrary.Tran_info.ByReference();
info1.m_oil = (float) params.getM_oil();
info1.m_wd = (float) params.getM_wd();
info1.n_fanAF = params.getN_fanAF();
info1.n_fan = params.getN_fan();
info1.n_fanwork = params.getN_fanwork();
info1.R_H = CommomUtils.parseArray(params.getR_H());//二維轉一維
TieeLibrary.Time_info.ByReference info2 = new TieeLibrary.Time_info.ByReference();
info2.U = (float) params.getU();
info2.i_H = (float) params.geti_H();
info2.i_M = (float) params.geti_M();
info2.i_L = (float) params.geti_L();
info2.T_now = params.getT_now();
TieeLibrary.data_out.ByReference data = new TieeLibrary.data_out.ByReference();
System.out.println("before monitor");
System.out.println("info1:" + info1.toString());
TieeLibrary.INSTANCE.monitor(info1, info2, data);
System.out.println("after monitor");
System.out.println("tmp1:" + data.tmp1 + " tmp2:" + data.tmp2 + " tmp1:" + data.tmp3);
System.out.println("load_min[0]:" + data.load_min[0] + " load_min[1]:" + data.load_min[1] + " load_min[2]:"
+ data.load_min[2]);
System.out.println(" load_min[3]:" + data.load_min[3] + " load_min[4]:" + data.load_min[4] + " load_min[5]:"
+ data.load_min[5]);
out.setTmp1(data.tmp1);
return out;
}
}
若發現不當之處,歡迎留言指出!