1. 程式人生 > >jna對結構體、指標、引用、拷貝引數傳遞的使用

jna對結構體、指標、引用、拷貝引數傳遞的使用

雖然之前也用過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用檢視器檢視:


C++測試程式碼:
// dllUse.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include "stdlib.h"
#include "dllTest.h"


int _tmain(int argc, _TCHAR* argv[])
{
	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;
}

執行結果:


——————————————————————————————————————————————————————————

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


執行結果:


結論:

1.只要涉及到結構體的傳遞,必須使用ByReference或者ByValue中的一種

2.指標引用的傳遞使用ByReference

2.拷貝引數傳遞使用ByValue

如果編譯好的dll在jna中提示不能找到該函式,請注意是否使用了extern “C” 關鍵字。或者使用dll檢視器看一下