2013-07-09 264 views
0

我想在C DLL中調用一個函數,該函數需要一個指向結構體的指針。這個結構(Data)的定義是這樣的:如何使用指向Java指針的指針填充結構?

struct BD 
{ 
    char* Data; 
    int Length; 
}; 

struct EE 
{ 
    char* Key; 
    BD* Value; 
}; 

struct Data 
{ 
    char* Name; 
    BD* Picture; 

    // A NULL-terminated array of pointers to EE structures. 
    EE** Elements; 
}; 

在Java中我已經定義了一些類,像這樣:

public static class BD extends Structure implements Structure.ByReference { 
    public byte[] Data; 
    public int Length; 
} 

public static class EE extends Structure implements Structure.ByReference { 
    public String Key; 
    public BD Value; 
} 

public static class Data extends Structure { 
    public String Name; 
    public BD Picture; 
    public PointerByReference Elements; 
} 

但現在我不知道究竟如何填充Data對象正確。我想我可以計算出NamePicture字段,但是我怎樣將Elements字段設置爲?我可以創建一個EE對象的Java數組,但是如何從中獲取PointerByReference?也許我需要將Elements聲明爲Pointer[],但是接下來我只需要爲每個EE對象填充數組的每個元素,即getPointer()對象?雖然這看起來不太合適?

編輯:給的什麼,我試圖做一個更好的主意:

Data data = new Data(); 
// Fill in Name and Picture fields. 

EE[] elements = new Elements[10]; 
// Fill in the elements array. 

// Now how do I set the Elements field on the data object from the elements array? 
data.Elements = ??? 

EDIT2:這是我如何與technomage的幫助下解決了這個問題:

我改變了我的Data結構看起來像這樣:

public static class Data extends Structure { 
    public String Name; 
    public BD Picture; 
    public Pointer Elements; 
} 

而我的BD結構是這樣的:

public static class BD extends Structure implements Structure.ByReference { 
    public Pointer Data; 
    public int Length; 
} 

將Java byte[]轉換爲JNA Pointer我不得不使用ByteBuffer

ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length); 
buf.put(bytes); 
bd.Data = Natvie.getDirectBufferPointer(buf); 

JNA不以struture喜歡ByteBuffer小號不幸。

爲了讓我的元素的指針,我需要創建的Pointer s到每個EE對象的數組(參見technomage的答案PointerArray實現):

EE e = new EE(); 
// Populate e object. 
// ... 

// Important: ensure that the contents of the objects are written out to native memory since JNA can't do this automatically 
e.write(); 
ptrs.add(e); 

// Once each object is setup we can simply take the array of pointers and use the PointerArray 
data.Elements = new PointerArray(ptrs.toArray(new Pointer[0])); 

我不能使用ByteBufferPointerArray直接在結構定義,所以我不得不依靠Pointer

+0

當您另外傳遞指針變量的地址時,將使用'PointerByReference',以便爲被調用者提供空間以「返回」一個值。 – technomage

+0

如果您的本地'struct'使用'char []'作爲相應的字段類型,則只能使用'byte []'作爲'Structure'字段。 – technomage

回答

1

製作Elements a Pointer,然後使用Pointer.getPointerArray(0)來檢索感興趣的結構指針。

然後,您需要初始化每個Structure從每個檢索的Pointer(不要忘記撥打Structure.read())。

沒有辦法在指針上自動執行間接尋址,並且結束了一個Structure的數組,但它很容易編碼到Structure類中的方法(例如Data.getElements())。

編輯

採樣指針數組實現,初始化上寫的指針數組(而不是讀):

class PointerArray extends Memory {      
     private final Pointer[] original;               
     public PointerArray(Pointer[] arg) {               
      super(Pointer.SIZE * (arg.length+1));             
      this.original = arg;                  
      for (int i=0;i < arg.length;i++) {              
       setPointer(i*Pointer.SIZE, arg[i]);             
      }                      
      setPointer(Pointer.SIZE*arg.length, null);            
     }                       
    } 
} 

您還需要調用本地函數(之前調用Structure.write()你可以這樣做,作爲PointerArray的一部分),因爲當你使用香草Pointer而不是Structure時,JNA不知道內存需要同步。

+0

我需要在Java中填充'Data'對象並將其傳遞給本機函數。所以我想我需要將'EE []'轉換爲'Pointer'? – JasonA

+0

請參閱答案編輯中的示例指針數組實現。 – technomage

+0

好吧,看起來很像我需要的東西。但是,我嘗試了它,但它仍然無法正常工作。當我用調試器進入本地函數時,data-> Elements有一個值,但data-> Elements [0]爲空。也許我還在做錯了什麼?我現在將元素字段定義爲指針,並將'data.Elements'設置爲'new PointerArray(arrayOfPointers)'。 – JasonA