`
xiang37
  • 浏览: 429467 次
  • 性别: 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

 

分享到:
评论

相关推荐

    java通过jna返回结构体例子.rar

    在Linux环境下运行,你需要确保JNA库和编译好的C库(动态链接库.so)都在正确的位置,或者在Java代码中指定了正确的路径。此外,操作步骤文档应该详细指导如何编译C代码,打包Java项目,以及如何执行程序。 总结,...

    JNA 复杂结构体传递

    `ProcessLibrary`是包含`processStructArray`方法的接口,`Native.loadLibrary`用于加载动态链接库。 最后,处理结构体指针。在C中,结构体指针常用于传递大量数据或避免复制结构体。JNA通过`ByReference`和`By...

    JNA调用c/c++库示例

    如果`mylib`是一个动态链接库(.dll on Windows, .so on Linux, .dylib on macOS),加载代码如下: ```java MyLib myLib = (MyLib) Native.load("mylib", MyLib.class); ``` 现在,你可以像调用Java方法一样调用`...

    Jna调用动态库相关jar包

    标题中的"Jna调用动态库相关jar包"指的是使用JNA库来调用DLL动态链接库的Java应用程序所需的依赖文件。在描述中提到了两个关键的jar包: 1. **jna-3.5.1.jar**:这是JNA的主要库文件,包含了JNA的核心功能,包括...

    深入浅出JNA—快速调用原生函数

    JNI 允许 Java 程序和用其他编程语言编写的代码之间进行交互,不过使用 JNI 的难度较高,需要开发者同时具备 Java 和原生语言(如 C/C++)的知识,且需编写额外的动态链接库。因此,它常常让开发者望而却步。 JNA...

    JNA 4.1.0 官方版

    JNA的工作原理是通过动态加载动态链接库(DLL on Windows,.so on Linux,dylib on Mac OS X),并将Java方法映射到原生函数。它支持多种数据类型的自动转换,包括基本类型、数组、结构体、枚举和指针。此外,JNA还...

    java用JNA调用dll实例,包含各种参数调用

    Java语言在与操作系统底层交互时,通常会遇到需要调用动态链接库(DLL)的情况,尤其是在Windows平台上。Java Native Access(JNA)是Java平台上的一个开源库,它提供了直接调用系统DLL函数的能力,无需编写C代码...

    jna java 调用c动态库

    【JNA——JNI的终结者】 Java Native Access(JNA)是一种开源的Java框架,它为...无论是简单的函数调用还是复杂的本地库交互,JNA都提供了一种高效且易于维护的方式。如果你需要在Java中调用C代码,JNA绝对值得尝试。

    jna-3.3.0 & jna-3.3.0-platform

    它包含了一组动态链接库(DLL)加载器和内存管理机制,以及将Java方法映射到本地函数的类和接口。 - `com.sun.jna.Native`是JNA的核心类,用于加载本地库,并提供了各种方法来调用本地函数。 - `...

    JNA 调用dll jna调用 c++

    在标题和描述中提到的“JNA调用dll jna调用c++”是指利用JNA来调用Windows系统中的动态链接库(.dll)文件,这些.dll文件通常由C++或其他支持编译为本地代码的语言编写。 本文将详细介绍如何使用JNA进行dll调用,并...

    jna3.2.1.rar

    1. **JNA架构**:JNA的核心设计是基于一个动态链接库(DLL或SO文件),这个库包含了一个映射机制,将Java中的方法映射到本地库的函数。通过`com.sun.jna.Library`接口,开发者可以定义本地库的函数签名,并通过实现...

    JAVA-JNA简单使用

    Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码与本地操作系统功能进行交互,无需编写C语言的动态链接库(DLL)或JNI(Java Native Interface)代码。JNA通过一种声明式的接口,使Java程序员...

    JNA的相关jarbao

    Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码与本地操作系统功能进行交互,无需编写C语言的动态链接库或Java Native Interface(JNI)代码。JNA提供了一种简单的方法来调用操作系统API,以及...

    JNA的jar包

    使用JNA,开发者可以方便地调用动态链接库(DLL on Windows, shared libraries on macOS/Linux)中的C函数。JNA通过一种映射机制,将Java方法与C函数对应起来,这样在Java代码中调用Java方法时,实际上会触发对底层C...

    jna-4.5.2,此版本不需要libjnidispatch.so

    标题提到的"jna-4.5.2"是JNA的一个特定版本,这个版本的一个显著特点是它不需要`libjnidispatch.so`动态链接库。这个库通常用于在Java应用程序中加载和调用本地库的函数。 在JNA的早期版本中,如4.5.2,JNA库的实现...

    java调用C语言编写的so库中的函数,java调用C语言编写的dll库中的函数

    4. **加载库和调用函数**:在Java中,使用`System.loadLibrary("库名")`加载动态链接库,然后通过`native`关键字声明的本地方法调用库中的函数。 例如,`java jni调用so中的函数api.txt`中可能包含了具体的JNI函数...

    android JNA 依赖jar 包

    - Android系统对动态链接库的加载有特殊要求,需要确保.so文件与设备的架构兼容(armeabi, armeabi-v7a, x86, arm64-v8a等)。 - 将.so文件放置在项目的`jniLibs`目录下,对应于不同架构的子目录中。 - 需要处理...

    jna 小例子

    这个“jna小例子”可能是一个示例项目,展示了如何使用JNA与C或C++编写的DLL(动态链接库)进行交互。下面将详细阐述JNA的相关知识点。 ### JNA简介 JNA提供了一种方便的机制,使得Java程序可以无缝地访问本地库中...

    JNA实现回调及其他

    JNA(Java Native Access)是Java平台上的一个开源库,它允许Java程序直接调用本地(操作系统级别的)动态链接库(DLLs或.so文件),无需编写JNI(Java Native Interface)代码。JNA通过一种映射机制,将Java方法与C...

    jna-5.5.0.tar.gz

    2. **加载Library**:使用`Library`注解标记接口,指定要加载的动态链接库(DLL或SO文件)。 3. **调用函数**:通过接口实例来调用本地函数。 例如: ```java @Library("mylib") // 指定动态库名 public interface ...

Global site tag (gtag.js) - Google Analytics