天天看点

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

}
           

若发现不当之处,欢迎留言指出! 

继续阅读