java调用动态库dll/so(四)动态库加载框架的使用举例

目录

一、过程

二、建立C++动态库工程并编写接口

三、拷贝dll编写java接口进行编译


一、过程

  1. 编写C++动态库并导出;
  2. 使用动态库框架加载编写的动态库。

二、建立C++动态库工程并编写接口

(1)使用qt creator创建library库程序,工程结构如下图所示,具有三个.h头文件,一个ctest.cpp类文件。

其中ctest_global.h为工程自动生成,各文件功能描述如下:

文件名 功能 引用关系
ctest.h 定义导出接口

引用ctestdata.h

引用ctest_global.h

ctestdata.h 定义数据结构体和方法的声明  
ctest.cpp 函数接口封装类 引用ctest.h

(2)ctest.h中,具有三个导出函数接口:求和、获取手动结果、注册回调。这三个函数接口都是我为了测试怎样调用和传参杜撰的,没有具体意义。ctest.h代码如下所示:

#ifndef CTEST_H
#define CTEST_H

#include "ctest_global.h"
#include "ctestdata.h"

class CTESTSHARED_EXPORT CTest
{

public:
    CTest();
};

#endif // CTEST_H



//导出结果
extern "C"{

//求和
int sum(int a,int b);

//获取手动结果
int Target_Manual(FILETIME ftStartTime,FILETIME ftEndTime,Target* pTargets,int& nNum);

//注册回调
int RegisterReceiveDataCallBack(ReceiveData func);
}

(3)ctestdata.h如下所示:

#ifndef CESTDATA_H
#define CESTDATA_H

#endif // CESTDATA_H

typedef unsigned long DWORD;

typedef struct _FILETIME {
    DWORD dwLowDateTime;
    DWORD dwHighDateTime;
} FILETIME;

struct Target
{
    int nFrq;
    FILETIME ftFindTime;		//发现时间
    float fLong;				//经度
    float fLat;					//纬度
    char szLoc[20];			    //位置
    Target()
    {
    }
};

//回调接口
typedef int ReceiveData(Target* pTarget,int nCount);

(4)导出类ctest.cpp

#include "ctest.h"

CTest::CTest()
{
}

Q_DECL_EXPORT int sum(int a, int b)
{
    return a+b;
}

Q_DECL_EXPORT int Target_Manual(FILETIME ftStartTime,FILETIME ftEndTime,Target* pTargets,int& nNum)
 {
     return -1;
 }

Q_DECL_EXPORT int RegisterReceiveDataCallBack(ReceiveData func)
 {
     return 0;
 }

三、拷贝dll编写java接口进行编译

(1)在工程上鼠标右键单击弹出编译选项,依次执行qmake->构建即可生成dll库,将dll库拷贝至j动态库加载框架的工程目录resources/lib/windows目录下

(2)编写与调用库匹配的函数接口

        a.依照C++头文件定义接构体类

        b.依照C++头文件定义如下java接口;

结构体类StruTarget:

package maoko.dllSolibLoad.lib.model.struct.meta;

import maoko.dllSolibLoad.lib.model.struct.JavaStructBase;

/**
 * 目标信息
 * 
 * @author fanpei
 *
 */
public class StruTarget extends JavaStructBase {
	public int nFrq;// 频率
	public StruFileTime.ByValue ftFindTime; // 时间
	public float fLong; // 经度
	public float fLat; // 纬度
	public String szLoc; // 所属地名
}

结构体类StruFileTime

package maoko.dllSolibLoad.lib.model.struct.meta;

import com.sun.jna.NativeLong;

import maoko.dllSolibLoad.lib.model.struct.JavaStructBase;

/**
 * 时间信息
 * 
 * @author fanpei
 *
 */
public class StruFileTime extends JavaStructBase {
	public NativeLong dwLowDateTime;// 开始时间
	public NativeLong dwHighDateTime;// 结束时间
}

java接口ICTest

package maoko.dllSolibLoad.lib.load.ifs;

import com.sun.jna.Library;

import maoko.dllSolibLoad.lib.load.LibLoad;
import maoko.dllSolibLoad.lib.model.struct.meta.StruFileTime;
import maoko.dllSolibLoad.lib.model.struct.meta.StruTarget;

/**
 * 加载动态库接口
 * 
 * @author fanpei
 *
 */
@LibLoad(linuxName = "libCTest", windowsName = "CTest")
public interface ICTest extends Library {

	/**
	 * 求和
	 * 
	 * @param a 数据a
	 * @param b 数据b
	 * @return 返回两数之和
	 */
	int sum(int a, int b);

	/**
	 * 手动处理数据
	 * 
	 * @param ftStartTime 开始时间
	 * @param ftEndTime   结束时间
	 * @param pTarget     待处理数组的地址
	 * @param nNum        待处理数组个数
	 * @return
	 */
	int Target_Manual(StruFileTime.ByValue ftStartTime, StruFileTime.ByValue ftEndTime, StruTarget.ByReference pTarget,
			int nNum);

	/**
	 * 注册回调-用于异步返回数据
	 * 
	 * @param func
	 * @return
	 */
	int RegisterReceiveDataCallBack(ICallBack func);

	/**
	 * 回调接口
	 * 
	 * @author fanpei
	 *
	 */
	public interface ICallBack {

		/**
		 * 回调函数
		 * 
		 * @param targets 结果数据
		 * @param nNum    结果个数
		 * @return
		 */
		public abstract int ReceiveCrossData(StruTarget.ByReference targets, int nNum);
	}
}

设置JnaLibCall中的接口目录静态变量为ICTest接口所在包名,如下图所示:

最后运行框架,调用sum接口效果如下图所示:

代码完整地址:https://download.csdn.net/download/fanpei_moukoy/11195072

                         https://github.com/maokofan/maoko.dllSoLibLoad

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章