簡體   English   中英

JNA 中的 Marshal.StructureToPtr Java 等效項

[英]Marshal.StructureToPtr Java equivalent in JNA

我正在開發一個項目,我必須與之通信的唯一庫是一個 .dll 文件,而我擁有的資源是一個帶有源代碼的 C# 工作項目; 我正在使用 JNA 訪問本機代碼,並且當前在調用該方法時遇到了無效的內存訪問;

代碼:

[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()的文檔為您提供了有關您需要做什么的強烈提示:

將數據從托管對象編組到非托管內存塊。

structure保存要封送的數據的托管對象。 此對象必須是格式化類的結構或實例。

ptr指向非托管內存塊的指針,必須在調用此方法之前分配該內存塊。

您有結構參數,但您需要分配第二個參數所需的內存塊。 這可以通過 JNA 的Memory類來完成。

更復雜的是,您需要傳遞的結構實際上包含其他結構的數組,並且必須在連續內存中分配。 您在RSSlapInfoArray包裝中完成此操作的方式實際上根本沒有分配任何內存; 它只是聲明了一個帶有空指針的 java 端數組,該數組將傳遞給本機端。

您需要做的第一件事是更正您的RSSlapInfoArray映射以連續分配結構數組。 改變

public RSSlapInfo RSSlapInfoA[] = new RSSlapInfo[4]; // does not allocate anything

public RSSlapInfo[] RSSlapInfoA = (RSSlapInfo[]) new RSSlapInfo().toArray(4); // contiguous allocation 

您應該對RSPoint數組執行類似的RSPoint

public RSPoint[] fingerPosition = new RSPoint().toArray(4);

關於您的結構映射的另一個注意事項:您在沒有實現它的情況下覆蓋了Structure類構造函數。 您應該刪除(不需要的)構造函數或在構造函數中調用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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM