`
xiang37
  • 浏览: 414158 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

JNA与动态链接库交互之使用结构体与结构体数组

阅读更多

        Java调用C/C++动态链接库函数,当传递参数为结构体且结构体存在数组的情况时,则传参的数组长度要和C/C++语言定义的长度一致。

 

import java.util.ArrayList;
import java.util.List;

import com.sun.jna.Structure;

/**
 * 
 * @author XIVA
 *
 */
public class DevInfo extends Structure
{


    public byte[] pProtocolType = new byte[20];

    public int nDevType = 0;

    public byte[] pDevIP = new byte[20];

    public int nDevPort = 0;

    public byte[] pDevUsername = new byte[64];

    public byte[] pDevPassword = new byte[64];

    public byte[] pVendorType = new byte[20];

    public static class ByReference extends HwDevInfo implements Structure.ByReference
    {
    }

    public static class ByValue extends HwDevInfo implements Structure.ByValue
    {
    }

    @Override
    protected List<String> getFieldOrder()
    {
        List<String> fieldOrderList = new ArrayList<String>();
        fieldOrderList.add("pProtocolType");
        fieldOrderList.add("nDevType");
        fieldOrderList.add("pDevIP");
        fieldOrderList.add("nDevPort");
        fieldOrderList.add("pDevUsername");
        fieldOrderList.add("pDevPassword");
        fieldOrderList.add("pVendorType");
        
        return fieldOrderList;
    }
}

 接口声明:

public int Camera_AddDevice(String pTargetDomainCode, String pTargetDevGroupID, DevInfo.ByReference  pDevInfo, byte[] pDevCode);

 

结构体声明:

typedef struct _DevInfo
{
    char pProtocolType[20]; 
    int nDevType; 
    char pDevIP[20];
    int nDevPort;
    char pDevUsername[64];
    char pDevPassword[64];
    char pVendorType[20];
    _DevInfo()
    {
        nDevPort = 0;
        nDevType = 0;
        ZeroMemory(pProtocolType, sizeof(pProtocolType));
        ZeroMemory(pDevIP, sizeof(pDevIP));
        ZeroMemory(pDevUsername, sizeof(pDevUsername));
        ZeroMemory(pDevPassword, sizeof(pDevPassword));
        ZeroMemory(pVendorType, sizeof(pVendorType));
    }
}DEVINFO, *LPDEVINFO;

 

#define JNAAPI  extern "C" _declspec(dllexport)

JNAAPI int Camera_AddDevice(const char * pTargetDomainCode, const char * pTargetDevGroupID, 
                                         LPDEVINFO pDevInfo, OUT char * pDevCode);

 

声明了以上函数后,就是JAVA调用了。

 

DevInfo.ByReference pDevInfo = new DevInfo.ByReference();
            byte[] ipBytes = "127.0.0.1".getBytes();
            byte[] pDevUsernameBytes = "admin".getBytes();
            byte[] pDevPasswordBytes = "admin".getBytes();
            byte[] pVendorTypeBytes = "xxx".getBytes();
            byte[] pProtocolTypeBytes = "xxx".getBytes();
            
            System.arraycopy(ipBytes, 0, pDevInfo.pDevIP, 0, Math.min(ipBytes.length, pDevInfo.pDevIP.length));
            System.arraycopy(pDevUsernameBytes, 0, pDevInfo.pDevUsername, 0, Math.min(ipBytes.length, pDevInfo.pDevUsername.length));
            System.arraycopy(pDevPasswordBytes, 0, pDevInfo.pDevPassword, 0, Math.min(ipBytes.length, pDevInfo.pDevPassword.length));
            System.arraycopy(pVendorTypeBytes, 0, pDevInfo.pVendorType, 0, Math.min(ipBytes.length, pDevInfo.pVendorType.length));
            System.arraycopy(pProtocolTypeBytes, 0, pDevInfo.pProtocolType, 0, Math.min(ipBytes.length, pDevInfo.pProtocolType.length));
            
            pDevInfo.nDevPort = 8080;
            pDevInfo.nDevType = 1;
            
            
            String pDevCode = CommHWService.Camera_AddDevice("xxxx", "0", pDevInfo);

 其中最为重要的代码是将值复制到声明的内存区域,

System.arraycopy(ipBytes, 0, pDevInfo.pDevIP, 0, Math.min(ipBytes.length, pDevInfo.pDevIP.length));

,而不是直接赋值:pDevInfo.pDevUsername = "admin".getBytes();

如果使用以下方式实现,内存会发生泄漏,导致JVM报错。

 

原因就是JVM声明的结构体和C端定义的结构体对应的内存区域大小不一致。

 

另外:

1、对象pDevInfo初始化的时候没有初始化其属性,则可以使用工具类Arrays的方法public static byte[] copyOf(byte[] original, int newLength)。

2、当传递参数为结构体数组时,我们需要使用连续的内存区域。可以使用反射类Array来初始化对象。如:((DevInfo[])Array.newInstance(DevInfo.class, 10));

 

参考:http://tcspecial.iteye.com/blog/1665583

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics