带有Windows DLL的JNA,带结构指针的回调函数指针,无效的内存访问

时间:2016-02-28 20:13:18

标签: java c++ dll dllimport jna

我的问题是我试图通过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界面?我做错了什么?

更新: 这是堆栈跟踪的JPG: enter image description here

0 个答案:

没有答案