jna官网地址:https://jna.dev.java.net/
首先写了一个用于测试的DLL文件:
FirstDLL.h头文件:
#ifdef FirstDLL_API #else #define FirstDLL_API extern "C" _declspec(dllimport) #endif typedef struct{ char* userName; int age; char* tel; }User; FirstDLL_API int GetSum(int a,int b); FirstDLL_API char* CallChar(char* a); FirstDLL_API void CallPointer(int *a); FirstDLL_API void CallPIntArray(int *a,int len); FirstDLL_API int CallStruct(User &user); FirstDLL_API int CallStructArray(User *user,int len); FirstDLL_API void CallVRef(int a,int b,int &c);
FirstDLL.cpp文件:
#define FirstDLL_API extern "C" _declspec(dllexport) #include "FirstDLL.h" #include <iostream.h> int GetSum(int a,int b) { return a+b; } char* CallChar(char* a){ return a; } int CallStruct(User &user){ user.userName = "陈均"; user.age = 22; user.tel = "8888888"; return 0; } int CallStructArray(User *user,int len){ for(int i = 0;i<len;i++) { user->userName = "陈均"; user->age = i+1; user->tel = "电话"; user++; } return 0; } void CallPointer(int *a){ *a = 5; } void CallPIntArray(int *a,int len){ for(int i = 0;i<len;i++){ *a = i+3; a++; } } void CallVRef(int a,int b,int &c){ c = a + b; }
编译后生成FirstDLL.dll文件.
测试文件FirstDLLTest:如果是Delphi写的DLL,将下面的生命改成如下格式即可
typedef int (FAR PASCAL *SetSrvProc)(int srv,int zh,int jh);
#include <iostream.h> #include <WINDOWS.H> #include <WINBASE.H> HINSTANCE first_dll = NULL; //声明结构体类型 typedef struct{ char* userName; int age; char* tel; }User; //外部dll声明 typedef int (*GetSumProc)(int a,int b); typedef int (*CallStructProc)(User &user); typedef int (*CallStructArrayProc)(User *user,int len); typedef void (*CallPointerProc)(int *a); typedef void (*CallPIntArrayProc)(int *a,int len); typedef void (*callVRefProc)(int a,int b,int &c); //结构体声明 typedef struct{ int kh;//0x0000,0x0001,0x0002,0x0003 unsigned char mu;//0x0004 short qty;// 0x0006,0x0007 int je;// 0x0008,0x0009,0x000A,0x000B int ye;// 0x000C,0x000D,0x000E,0x000F unsigned short year;//0x0010,0x0011 unsigned char month,day,hour,minute,second,ms,sd;//0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018 unsigned char jh;//0x0019 unsigned char lb;//0x001A unsigned char online;//0x001B //如果对齐设置默认8则:0x0000-0x001B共28个字节-->4倍 28 //如果对齐设置1则:0x0000-0x001A共27个字符 }PKQRCDA; void main() { User user; User array[2]; //调用外部dll的GetSum方法 first_dll = LoadLibrary("E:\\C++WORK\\FirstDLL\\Debug\\FirstDLL.dll"); if(first_dll!=NULL){ GetSumProc getSum = (GetSumProc)GetProcAddress(first_dll,"GetSum"); int result = getSum(4,5); cout<<result<<endl; CallStructProc callStruct = (CallStructProc)GetProcAddress(first_dll,"CallStruct"); result = callStruct(user); cout<<user.userName<<endl; CallStructArrayProc callStructArray = (CallStructArrayProc)GetProcAddress(first_dll,"CallStructArray"); result = callStructArray(array,2); cout<<array[0].age<<endl; CallPointerProc callPointer = (CallPointerProc)GetProcAddress(first_dll,"CallPointer"); int a = 3; callPointer(&a); cout<<a<<endl; CallPIntArrayProc calPIntArray = (CallPIntArrayProc)GetProcAddress(first_dll,"CallPIntArray"); int len = 3; int pia[20]; calPIntArray(pia,len); callVRefProc calVRef = (callVRefProc)GetProcAddress(first_dll,"CallVRef"); int c; calVRef(4,7,c); } }
以下是java测试:
IFirstDLL接口文件:
public interface IFirstDLL extends Library { //绝对路径,在开发的时候可以这样写,方便更新 IFirstDLL INSTANCE = (IFirstDLL) Native.loadLibrary("E:\\C++WORK\\FirstDLL\\Debug\\FirstDLL.dll", IFirstDLL.class); //相对路径,在不修改dll的时候可放到jdk/bin下面或者system32 //IFirstDLL INSTANCE = (IFirstDLL) Native.loadLibrary("FirstDLL", IFirstDLL.class); //下面是dll对应的接口方法声明,参数类型和返回类型要一致 //结构体声明 public static class User extends Structure{ public String userName; public int age; public String tel; } //值传递 int GetSum(int a,int b); //字符串传递 String CallChar(String a); //整形指针传递 void CallPointer(IntByReference a); //整形数组传递,c指针变量 void CallPIntArray(int []a,int len); //结构体值传递 public int CallStruct(User user); //结构体数组传递,结构体指针变量接收 public int CallStructArray(User[] user,int len); //带返回值的传递 public void CallVRef(int a,int b,IntByReference c); }
测试文件IFirstDLLTest:
public class IFirstDLLTest { public static void main(String[] args) { IFirstDLL firstDLL = IFirstDLL.INSTANCE; int a = 4; int b = 6; firstDLL.GetSum(a, b); firstDLL.CallChar("字符串内容"); IntByReference d = new IntByReference(); firstDLL.CallPointer(d); int[] e = new int[2]; firstDLL.CallPIntArray(e, e.length); User user = new User(); firstDLL.CallStruct(user); System.out.println("userName:" + user.userName+";age=" + user.age + ";tel=" + user.tel); User[]users = new User[3]; firstDLL.CallStructArray(users, users.length); IntByReference c = new IntByReference(); firstDLL.CallVRef(3, 5, c); } }
搞定了,常用的交互基本上都有了。复杂的也是这些演变出来的。
附件包含上面3个工程。