天天看點

jna傳遞結構體參數調用so動态庫 一 、封裝動态庫二   java調用類

一 、封裝動态庫

   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;
	}

}
           

若發現不當之處,歡迎留言指出! 

繼續閱讀