Marshal.StructureToPtr Java 相当于 JNA
Marshal.StructureToPtr Java equivalent in JNA
我正在做一个项目,我必须与之通信的唯一库是一个 .dll 文件,我拥有的资源是一个带有源代码的 C# 工作项目;我正在使用 JNA 访问本机代码,目前我在调用该方法时 运行 进入无效内存访问;
c#代码:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct RSSlapInfo
{
public int fingerType;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public RSPoint[] fingerPosition;
public int imageQuality;
public int rotation;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public int[] reserved;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct RSSlapInfoArray
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public RSSlapInfo[] RSSlapInfoA;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct RSPoint
{
public int x;
public int y;
};
RSSlapInfoArray slapInfoA = new RSSlapInfoArray();
IntPtr slapInfoArray;
int _size = Marshal.SizeOf(typeof(RSSlapInfoArray));
slapInfoArray = Marshal.AllocHGlobal(_size);
Marshal.StructureToPtr(slapInfoA, slapInfoArray, true);
在调试模式下,我注意到 slapInfoArray
值在上述调用后发生了变化
我的Java代码:
public static class RSSlapInfo extends Structure
{
public RSSlapInfo(){}
public int fingerType;
public RSPoint[] fingerPosition = new RSPoint[4];
public int imageQuality;
public int rotation;
public int[] reserved =new int[3];
}
@Structure.FieldOrder({"RSSlapInfoA"})
public static class RSSlapInfoArray extends Structure implements Structure.ByValue
{
public RSSlapInfoArray() {
}
public RSSlapInfo RSSlapInfoA[] = new RSSlapInfo[4];
}
@Structure.FieldOrder({"x","y"})
public static class RSPoint extends Structure
{
public RSPoint(){
}
public int x;
public int y;
}
在使用 slapInfoArray
进行本机调用之前,目前仍停留在转换此 C# 部分代码的正确方法上
RSSlapInfoArray slapInfoA = new RSSlapInfoArray();
IntPtr slapInfoArray;
int _size = Marshal.SizeOf(typeof(RSSlapInfoArray));
slapInfoArray = Marshal.AllocHGlobal(_size);
Marshal.StructureToPtr(slapInfoA, slapInfoArray, true);
Marshal.StructureToPtr()
的文档为您提供了关于您需要做什么的强烈提示:
Marshals data from a managed object to an unmanaged block of memory.
structure
A managed object that holds the data to be marshaled. This object must be a structure or an instance of a formatted class.
ptr
A pointer to an unmanaged block of memory, which must be allocated before this method is called.
您有结构参数,但您需要分配第二个参数所需的内存块。这可以通过 JNA 的 Memory
class.
来完成
更复杂的是,您需要传递的结构实际上包含其他结构的数组,并且必须分配在连续的内存中。您在 RSSlapInfoArray
包装中执行此操作的方式实际上根本没有分配任何内存;它只是声明了一个 java-side 数组,其中包含将传递给本机端的空指针。
您需要做的第一件事是更正您的 RSSlapInfoArray
映射以连续分配结构数组。变化
public RSSlapInfo RSSlapInfoA[] = new RSSlapInfo[4]; // does not allocate anything
至
public RSSlapInfo[] RSSlapInfoA = (RSSlapInfo[]) new RSSlapInfo().toArray(4); // contiguous allocation
您应该对 RSPoint
数组执行类似的操作:
public RSPoint[] fingerPosition = new RSPoint().toArray(4);
关于你的结构映射的另一个注意事项:你已经覆盖了 Structure
class 构造函数而没有实现它。您应该删除(不需要的)构造函数或在构造函数中调用 super()
。
假设您已经在加载 DLL 的接口中映射了 StructureToPtr,类似于:
void StructureToPtr(Structure structure, Pointer ptr, boolean fDeleteOld);
那么你问题中最后 5 行的 JNA 代码应该是
// Create the managed structure with the array inline
RSSlapInfoArray slapInfoA = new RSSlapInfoArray();
// Allocate a block of memory for it
Memory slapInfoArray = new Memory(slapInfoA.size());
// Call StructureToPtr
YourInterface.INSTANCE.StructureToPtr(slapInfoA, slapInfoArray, true);
我正在做一个项目,我必须与之通信的唯一库是一个 .dll 文件,我拥有的资源是一个带有源代码的 C# 工作项目;我正在使用 JNA 访问本机代码,目前我在调用该方法时 运行 进入无效内存访问;
c#代码:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct RSSlapInfo
{
public int fingerType;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public RSPoint[] fingerPosition;
public int imageQuality;
public int rotation;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public int[] reserved;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct RSSlapInfoArray
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public RSSlapInfo[] RSSlapInfoA;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct RSPoint
{
public int x;
public int y;
};
RSSlapInfoArray slapInfoA = new RSSlapInfoArray();
IntPtr slapInfoArray;
int _size = Marshal.SizeOf(typeof(RSSlapInfoArray));
slapInfoArray = Marshal.AllocHGlobal(_size);
Marshal.StructureToPtr(slapInfoA, slapInfoArray, true);
在调试模式下,我注意到 slapInfoArray
值在上述调用后发生了变化
我的Java代码:
public static class RSSlapInfo extends Structure
{
public RSSlapInfo(){}
public int fingerType;
public RSPoint[] fingerPosition = new RSPoint[4];
public int imageQuality;
public int rotation;
public int[] reserved =new int[3];
}
@Structure.FieldOrder({"RSSlapInfoA"})
public static class RSSlapInfoArray extends Structure implements Structure.ByValue
{
public RSSlapInfoArray() {
}
public RSSlapInfo RSSlapInfoA[] = new RSSlapInfo[4];
}
@Structure.FieldOrder({"x","y"})
public static class RSPoint extends Structure
{
public RSPoint(){
}
public int x;
public int y;
}
在使用 slapInfoArray
RSSlapInfoArray slapInfoA = new RSSlapInfoArray();
IntPtr slapInfoArray;
int _size = Marshal.SizeOf(typeof(RSSlapInfoArray));
slapInfoArray = Marshal.AllocHGlobal(_size);
Marshal.StructureToPtr(slapInfoA, slapInfoArray, true);
Marshal.StructureToPtr()
的文档为您提供了关于您需要做什么的强烈提示:
Marshals data from a managed object to an unmanaged block of memory.
structure
A managed object that holds the data to be marshaled. This object must be a structure or an instance of a formatted class.
ptr
A pointer to an unmanaged block of memory, which must be allocated before this method is called.
您有结构参数,但您需要分配第二个参数所需的内存块。这可以通过 JNA 的 Memory
class.
更复杂的是,您需要传递的结构实际上包含其他结构的数组,并且必须分配在连续的内存中。您在 RSSlapInfoArray
包装中执行此操作的方式实际上根本没有分配任何内存;它只是声明了一个 java-side 数组,其中包含将传递给本机端的空指针。
您需要做的第一件事是更正您的 RSSlapInfoArray
映射以连续分配结构数组。变化
public RSSlapInfo RSSlapInfoA[] = new RSSlapInfo[4]; // does not allocate anything
至
public RSSlapInfo[] RSSlapInfoA = (RSSlapInfo[]) new RSSlapInfo().toArray(4); // contiguous allocation
您应该对 RSPoint
数组执行类似的操作:
public RSPoint[] fingerPosition = new RSPoint().toArray(4);
关于你的结构映射的另一个注意事项:你已经覆盖了 Structure
class 构造函数而没有实现它。您应该删除(不需要的)构造函数或在构造函数中调用 super()
。
假设您已经在加载 DLL 的接口中映射了 StructureToPtr,类似于:
void StructureToPtr(Structure structure, Pointer ptr, boolean fDeleteOld);
那么你问题中最后 5 行的 JNA 代码应该是
// Create the managed structure with the array inline
RSSlapInfoArray slapInfoA = new RSSlapInfoArray();
// Allocate a block of memory for it
Memory slapInfoArray = new Memory(slapInfoA.size());
// Call StructureToPtr
YourInterface.INSTANCE.StructureToPtr(slapInfoA, slapInfoArray, true);