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
相关推荐
在Linux环境下运行,你需要确保JNA库和编译好的C库(动态链接库.so)都在正确的位置,或者在Java代码中指定了正确的路径。此外,操作步骤文档应该详细指导如何编译C代码,打包Java项目,以及如何执行程序。 总结,...
`ProcessLibrary`是包含`processStructArray`方法的接口,`Native.loadLibrary`用于加载动态链接库。 最后,处理结构体指针。在C中,结构体指针常用于传递大量数据或避免复制结构体。JNA通过`ByReference`和`By...
如果`mylib`是一个动态链接库(.dll on Windows, .so on Linux, .dylib on macOS),加载代码如下: ```java MyLib myLib = (MyLib) Native.load("mylib", MyLib.class); ``` 现在,你可以像调用Java方法一样调用`...
标题中的"Jna调用动态库相关jar包"指的是使用JNA库来调用DLL动态链接库的Java应用程序所需的依赖文件。在描述中提到了两个关键的jar包: 1. **jna-3.5.1.jar**:这是JNA的主要库文件,包含了JNA的核心功能,包括...
JNI 允许 Java 程序和用其他编程语言编写的代码之间进行交互,不过使用 JNI 的难度较高,需要开发者同时具备 Java 和原生语言(如 C/C++)的知识,且需编写额外的动态链接库。因此,它常常让开发者望而却步。 JNA...
JNA的工作原理是通过动态加载动态链接库(DLL on Windows,.so on Linux,dylib on Mac OS X),并将Java方法映射到原生函数。它支持多种数据类型的自动转换,包括基本类型、数组、结构体、枚举和指针。此外,JNA还...
Java语言在与操作系统底层交互时,通常会遇到需要调用动态链接库(DLL)的情况,尤其是在Windows平台上。Java Native Access(JNA)是Java平台上的一个开源库,它提供了直接调用系统DLL函数的能力,无需编写C代码...
【JNA——JNI的终结者】 Java Native Access(JNA)是一种开源的Java框架,它为...无论是简单的函数调用还是复杂的本地库交互,JNA都提供了一种高效且易于维护的方式。如果你需要在Java中调用C代码,JNA绝对值得尝试。
它包含了一组动态链接库(DLL)加载器和内存管理机制,以及将Java方法映射到本地函数的类和接口。 - `com.sun.jna.Native`是JNA的核心类,用于加载本地库,并提供了各种方法来调用本地函数。 - `...
在标题和描述中提到的“JNA调用dll jna调用c++”是指利用JNA来调用Windows系统中的动态链接库(.dll)文件,这些.dll文件通常由C++或其他支持编译为本地代码的语言编写。 本文将详细介绍如何使用JNA进行dll调用,并...
1. **JNA架构**:JNA的核心设计是基于一个动态链接库(DLL或SO文件),这个库包含了一个映射机制,将Java中的方法映射到本地库的函数。通过`com.sun.jna.Library`接口,开发者可以定义本地库的函数签名,并通过实现...
Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码与本地操作系统功能进行交互,无需编写C语言的动态链接库(DLL)或JNI(Java Native Interface)代码。JNA通过一种声明式的接口,使Java程序员...
Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码与本地操作系统功能进行交互,无需编写C语言的动态链接库或Java Native Interface(JNI)代码。JNA提供了一种简单的方法来调用操作系统API,以及...
使用JNA,开发者可以方便地调用动态链接库(DLL on Windows, shared libraries on macOS/Linux)中的C函数。JNA通过一种映射机制,将Java方法与C函数对应起来,这样在Java代码中调用Java方法时,实际上会触发对底层C...
标题提到的"jna-4.5.2"是JNA的一个特定版本,这个版本的一个显著特点是它不需要`libjnidispatch.so`动态链接库。这个库通常用于在Java应用程序中加载和调用本地库的函数。 在JNA的早期版本中,如4.5.2,JNA库的实现...
4. **加载库和调用函数**:在Java中,使用`System.loadLibrary("库名")`加载动态链接库,然后通过`native`关键字声明的本地方法调用库中的函数。 例如,`java jni调用so中的函数api.txt`中可能包含了具体的JNI函数...
- Android系统对动态链接库的加载有特殊要求,需要确保.so文件与设备的架构兼容(armeabi, armeabi-v7a, x86, arm64-v8a等)。 - 将.so文件放置在项目的`jniLibs`目录下,对应于不同架构的子目录中。 - 需要处理...
这个“jna小例子”可能是一个示例项目,展示了如何使用JNA与C或C++编写的DLL(动态链接库)进行交互。下面将详细阐述JNA的相关知识点。 ### JNA简介 JNA提供了一种方便的机制,使得Java程序可以无缝地访问本地库中...
JNA(Java Native Access)是Java平台上的一个开源库,它允许Java程序直接调用本地(操作系统级别的)动态链接库(DLLs或.so文件),无需编写JNI(Java Native Interface)代码。JNA通过一种映射机制,将Java方法与C...
2. **加载Library**:使用`Library`注解标记接口,指定要加载的动态链接库(DLL或SO文件)。 3. **调用函数**:通过接口实例来调用本地函数。 例如: ```java @Library("mylib") // 指定动态库名 public interface ...