2016-08-04 42 views
0

私はJNAプログラミングにはかなり新しいです。私は以下のようなネイティブコードを持っていますJNA構造内の構造

int Data(int Number, aaa *Data, int* error); 

typedef struct { 
    uint8 Storage; 
    LStr path; 
    int32 chart; 
    int32 strt; 
    LStr val; 
    int32 timedata; 
    } aaa; 

typedef struct { 
    int32 cnt; /*num of bytes that follow*/  
    uChar str[1]; 
} LStrval, *LStrPtr, **LStr; 

JNAを使用してJavaからこのネイティブ関数を呼び出す方法を教えてください。私はいくつかのオプションを試しましたが、結果が得られません。私が試したオプションの1つは以下の通りです。

インタフェース機能

public int SetStorage_Data(int num,Storage_Data.ByReference data, Pointer error); 

public class Storage_Data extends Structure{ 
     public static class ByReference extends Storage_Data implements Structure.ByReference {} 

     public byte storage; 
     public Stringtype.ByReference savepath; 
     public int chart; 
     public int strt; 
     public Stringtype.ByReference val; 
     public int timedata; 

     @Override 
     protected List getFieldOrder() { 
      return Arrays.asList("storage", "savepath","chart", 
        "strt","val","timedata"); 
     } 
    } 



public class Stringtype extends Structure{ 
     public static class ByReference extends Stringtype implements Structure.ByReference { 

      public ByReference(int buffersize) { 
       super(buffersize); 
       // TODO Auto-generated constructor stub 
      }} 

     public int count; 
     public byte[] str; 

     public Stringtype(int buffersize) { 
      str = new byte[buffersize]; 
      count = str.length; 
      allocateMemory(); 
     } 

     @Override 
     protected List getFieldOrder() { 
      return Arrays.asList("count", "str"); 
     } 
    } 

とJavaコール

InjectionAnalyzerInterfaces.Storage_Data.ByReference storagedata = new InjectionAnalyzerInterfaces.Storage_Data.ByReference(); 

int len= string.length; 
InjectionAnalyzerInterfaces.Stringtype.ByReference savepath = new InjectionAnalyzerInterfaces.Stringtype.ByReference(len); 

      byte[] stringbyte = string.getBytes(); 
      System.arraycopy(stringbyte, 0, savepath.str, 0, bytes); 
      storagedata.savepath = savepath; 
      storagedata.chart = 1; 
      storagedata.strt =1; 
      String temp= "all"; 
      byte[] strtbyte = temp.getBytes(); 
      int dd = strtbyte.length; 
      InjectionAnalyzerInterfaces.Stringtype.ByReference stra = new InjectionAnalyzerInterfaces.Stringtype.ByReference(dd); 
      System.arraycopy(strtbyte, 0, stra.str,0, dd); 
      storagedata.strt = stra; 


      storagedata.tdata = 0; 

      Pointer error = new Memory(5); 

      int status1 = lib.Set_Config_Storage_Data(deviceNumber, storagedata, error); 

私を助けてください。事前にありがとう

+0

私は 'それから、さまざまなを使用して、あなたはそれらのフィールドのための' Pointer'を使用して開始するお勧めしますあなたが望むようにデータを抽出して書式設定するための「Pointer」アクセスメソッド。逆参照のレベルを理解したら、それをマップする最も賢明な方法を理解することができます。しかし、あなたのフィールドは 'struct **'であるという点で根本的な問題があります。これはJNAが認識しないため、 '構造体へのすべての呼び出しです。「読み書き」は、あなたが実行することに全面的に依存します。 – technomage

+0

@technomage 'Pointer.getPointer(0)'や 'PointerByReference.getValue()'を使う方が良いですか? –

+1

ポインターのアドレスをパラメーターとしてパラメーターに渡す場合にのみ、 'PointerByReference'を使用してください。もしあなたがフィールドのどこかに 'void **'を持っていたら、 'Pointer'を使います。 – technomage

答えて

0

あなたは正しい道を歩いています。

内部構造(LStrVal)を独自の構造クラスとして宣言する必要があります。 Stringtype構造でこれを行ったようですが、そこにいくつか変更する必要があります。

  • int argを使用してコンストラクタを削除します。あなたのC構造は、byte[]配列のサイズを1と指定します。その定数を使用してください。あなたはその後、外部構造、あなたはByReference部品

を必要としないsuper(p)

  • を呼び出すポインタ引数pのコンストラクタを必要とするsuper()
  • を呼び出し、引数なしのコンストラクタが必要
  • これらの構造体ポインタにPointerByReference型を使用し、メインコードでnew Stringtype(pbr.getValue())を使用してポインタを必要なクラスに変換します。

    代わりに、@technomageが示唆しているように、ポインタ型を使用してgetValue()の代わりにgetPointer(0)を使用します。要は、インスタンス変数として(ポインタへの)ポインタが必要であるということです。あなたLStrValを定義するには

  • +0

    'LStr'は' struct ** '型を持ち、' ​​struct.ByReference'にマップしません(構造体フィールドのコンテキスト内で 'struct *'になります)。 – technomage

    +0

    ちょうど再度読んで気付いて、私の答えを適切に編集しました。 –

    1

    、あなたは(少なくともで開始する)JNAを割り当てるためにどのくらいのメモリを知っているように、プリミティブ配列フィールドを初期化する必要があります。

    public byte str = new byte[1]; 
    

    あなたは右を行うにはStructure.read()をオーバーライドする必要があります事は、ネイティブメモリから初期化した後、読み取りにPointerベースのコンストラクタを提供する:最後に

    public void read() { 
        count = (int)readField("count"); 
        str = new byte[count]; 
        super.read(); 
    } 
    
    public LStr(Pointer p) { 
        super(p); 
        read(); 
    } 
    

    、あなた含む構造体は、struct**フィールド(全く分からない理由を持っています)、これはあなたがPointerにマッピングする必要があり、実際にあなたの所望の構造に変換するには便利な機能を提供します:

    public Pointer savepath; 
    public LStr getSavepath() { 
        return savepath != null ? new LStr(savepath.getPointer(0)) : null; 
    }