jna对结构体、指针、引用、拷贝参数传递的使用
2022-10-13 本文已影响0人
老鼠AI大米_Java全栈
虽然之前也用过jna,但是对于[结构体]的传递、指针参数数与返回值、引用参数与返回值、拷贝变量传递使用没有总结。
先上生成DLL代码:
dllTest.h
#ifndef DLLTEST_H
#define DLLTEST_H
struct myStruct
{
int a;
int b;
};
extern "C"{
__declspec(dllexport) int addNormal(myStruct ms);
__declspec(dllexport) void addPrt(myStruct *ms, int *ret);
__declspec(dllexport) int addRef(myStruct &ms);
};
#endif
dllTest.cpp : 定义 DLL 应用程序的导出函数
#include "stdafx.h"
#include "dllTest.h"
__declspec(dllexport) int addNormal(myStruct ms){
return ms.b + ms.a;
}
__declspec(dllexport) void addPrt(myStruct *ms, int *ret){
*ret = ms->a + ms->b + 1;
}
__declspec(dllexport) int addRef(myStruct &ms){
return ms.a + ms.b + 2;
}
生成的DLL用查看器查看:
image.png
C++测试代码:
dllUse.cpp : 定义控制台应用程序的入口点。
需要新建一个ConsoleApplication项目,将生成的test.h,test.dll,test.lib文件复制到项目中,与cpp文件同级并导入h和lib文件。
#include "MyDll.h"
#pragma comment(lib, "MyDll.lib") //使用注释方式引入库或编译目录
int main()
{
myStruct ms;
ms.a = 1;
ms.b = 2;
myStruct *pms = &ms;
printf("%d",addNormal(ms));
int sum;
addPrt(&ms,&sum);
printf("%d",sum);
printf("%d\n",addRef(ms));
system("Pause");
return 0;
}
运行结果:
image.png
java调用代码:
import java.util.ArrayList;
import java.util.List;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.ptr.IntByReference;
public interface dllTestApi extends Library {
public static dllTestApi dta = (dllTestApi)Native.loadLibrary("dllTest", dllTestApi.class);
public static class myStructur extends Structure{
public static class ByReference extends myStructur implements Structure.ByReference{
}
public static class ByValue extends myStructur implements Structure.ByValue{
}
public int a;
public int b;
@Override
protected List<String> getFieldOrder() {
List<String> Field = new ArrayList<String>();
Field.add("a");
Field.add("b");
return Field;
}
}
int addNormal(myStructur.ByValue ms);
void addPrt(myStructur.ByReference pms,IntByReference sum);
int addRef(myStructur.ByReference rms);
}
main:
import com.sun.jna.ptr.IntByReference;
public class test {
public static void main(String[] args){
dllTestApi.myStructur.ByReference pmysStructur = new dllTestApi.myStructur.ByReference();
pmysStructur.a = 1;
pmysStructur.b = 3;
IntByReference ib = new IntByReference();
dllTestApi.dta.addPrt(pmysStructur,ib);
System.out.println(ib.getValue());
System.out.println(dllTestApi.dta.addRef(pmysStructur));
dllTestApi.myStructur.ByValue vmysStructur = new dllTestApi.myStructur.ByValue();
vmysStructur.a = 1;
vmysStructur.b = 3;
System.out.println(dllTestApi.dta.addNormal(vmysStructur));
}
}
运行结果:
image.png
结论:
- 只要涉及到结构体的传递,必须使用ByReference或者ByValue中的一种
- 指针和引用的传递使用ByReference
- 拷贝参数传递使用ByValue
如果编译好的dll在jna中提示不能找到该函数,请注意是否使用了extern “C” 关键字。或者使用dll查看器看一下