一 、封装动态库
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;
}
}
若发现不当之处,欢迎留言指出!