目录
一、过程
- 编写C++动态库并导出;
- 使用动态库框架加载编写的动态库。
二、建立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