我的问题是我试图通过JNA将Windows DLL连接到我的Java程序,我收到的内存访问错误无法解决。
我有一个Windows(Vista 32位)DLL,它定义了几个函数,如下所示。我知道这很好用,因为我在Visual Studio 2008中编写了一个简单的测试程序,它加载DLL并运行函数。 DLL的标题如下:
typedef struct info_struct
{
char szSeries[12];
char szSerialNO[48];
unsigned int dwDeviceType;
int iResult;
unsigned char byIPv6MaskLen;
unsigned short wHttpPort;
unsigned char byRes[15];
} tMyCallbackInfo;
// Interface
typedef void (__stdcall *PMY_CALLBACK)(const tMyCallbackInfo; *lpCallbackInfo, void *pUserData);
extern "C"__declspec(dllimport) int __stdcall MYAPI_Start(PMY_CALLBACK pMyCallBack, int bInfo = 0, void* pUserData = NULL);
extern "C"__declspec(dllimport) int __stdcall MYAPI_Stop(void);
(这是实际代码的简化版本,显示了主要功能)。请注意,标头定义了一个回调函数指针,并将其传递给函数MYAPI_Start,函数指针将一个指向结构的指针作为参数。另请注意,C ++代码在该函数中使用默认参数值(C ++语言功能,而不是C语言功能)。
我的Java程序是:
//
// MyProg.java
package com.whatever.myprog;
import com.sun.jna.*;
import com.sun.jna.win32.*;
public class MyProg {
public MyProg() {
}
public void execute() {
int ret=0;
MyLibrary mylib = (MyLibrary)Native.loadLibrary("mydll", MyLibrary.class);
MyCallbackInterface callbackObj = new MyCallbackImpl();
System.out.println("Before MYAPI_Start");
ret=mylib.MYAPI_Start(callbackObj , 0, Pointer.NULL);
System.out.println("After MYAPI_Start, ret is "+ret);
}
public static void main(String[] args) {
try {
MyProg instance=new MyProg();
instance.execute();
} catch (UnsatisfiedLinkError e) {
System.out.println("Exception" + e);
}
}
}
这只会加载" mydll.dll"库并调用函数MYAPI_Start。 MyLibrary类的定义如下:
///////////////////////////////////////
// MyLibrary
///////////////////////////////////////
package com.whatever.myprog;
import com.sun.jna.*;
import com.sun.jna.win32.*;
public interface MyLibrary extends Library, StdCallLibrary {
public int MYAPI_Start(MyCallbackInterface pMyCallBack, int bInfo, Pointer pUserData);
public int MYAPI_Stop();
}
MyCallbackInterface的定义如下:
///////////////////////////////////////
// MyCallbackInterface
///////////////////////////////////////
package com.whatever.myprog;
import com.sun.jna.*;
import com.sun.jna.win32.*;
public interface MyCallbackInterface extends Callback, StdCallLibrary.StdCallCallback {
void invoke(MyCallbackInfoStruct lpCallbackInfo, Pointer pUserData);
}
并且实现定义如下:
///////////////////////////////////////
// MyCallbackImpl
///////////////////////////////////////
package com.whatever.myprog;
import com.sun.jna.*;
//
// define an implementation of the callback interface
//
public class MyCallbackImpl implements MyCallbackInterface {
@Override
public void invoke(MyCallbackInfoStruct lpCallbackInfo, Pointer pUserData) {
System.out.println("Called invoke in MyCallbackImpl ");
}
}
最后,结构MyCallbackInfoStruct(函数指针需要)定义如下:
///////////////////////////////////////
// MyCallbackInfoStruct
///////////////////////////////////////
package com.whatever.myprog;
import java.util.*;
import com.sun.jna.*;
public class MyCallbackInfoStruct extends Structure {
public byte[] szSeries=new byte[12];
public byte[] szSerialNO=new byte[48];
public int dwDeviceType;
public int iResult;
public byte byIPv6MaskLen;
public short wHttpPort;
public byte[] byRes=new byte[15];
@Override
protected List getFieldOrder() {
return Arrays.asList("szSeries","szSerialNO","dwDeviceType","iResult",
"byIPv6MaskLen","wHttpPort","byRes");
};
}
此类应正确建模头文件mydll.h。在我看来,我根据JNA文档正确地做了一切,但是在MYAPI_Start调用中我仍然遇到无效的内存访问错误。 com.sun.jna.win32中是否有一些我没有正确使用的Windows界面?我做错了什么?