0

私は次のコードを持っています:

public class TTM {

public interface WrapperDLL extends Library {
    WrapperDLL INSTANCE = (WrapperDLL) Native.loadLibrary("TransportRE", WrapperDLL.class);

    int TRE_send(int channel, Pointer data, int len);

}
public int Send (int channel, String data, int len) {
    WrapperDLL wdll = WrapperDLL.INSTANCE;

    Memory mem = new Memory(data.length()+1);
    mem.setString(0, data);
    int byteSent = wdll.TRE_send(channel_id, mem.getPointer(0), len);
    // at this (TRE_send) point the VM crashes !!!!

  return byteSent;
}

}

私が試したJNA APIを見てください:

public int Send (int channel, String data, int len) {
    WrapperDLL wdll = WrapperDLL.INSTANCE;

    Memory mem = new Memory(data.length()+1);
    mem.setString(0, data);
    int byteSent = wdll.TRE_send(channel_id, mem, len);

  return byteSent;
}

今回はクラッシュしませんが、正常に動作しません (byteSent = 0!)

いくつかのヒント?

4

2 に答える 2

1

String文字データではなくポインターが含まれているかのように逆参照しています。

Pointer.getPointer(0)指定されたポインタ アドレスからポインタ値を抽出しようとします。2番目のスニペットのように、ポインター値を直接渡したいと思うことは間違いありません。

JNA を使用すると、String値を直接渡すことができ、自動的に C 文字列 (NUL で終了するバイト配列) に変換されます。ただし、ネイティブ メソッドが文字列を必要としているかどうかは明確ではありません。特別にフォーマットされたバイトバッファが必要になる場合があります。

len送信するバッファの長さを意図している場合は、文字列の長さに 1 を加えた長さ (またはMemory渡す のサイズ) にする必要があります。

編集

DLL が常に にキャストすることを暗示していますchar *。その場合は、単純にそのまま渡す必要がStringあります。DLL が非 ASCII データを予期する場合がある場合は、Memoryそのメンバー関数を渡して使用し、目的のデータを書き込む必要があります。DLL の複数のバージョンを異なる署名で定義できることに注意してください。

  void send(String);
  void send(Pointer);
  void send(MyStructure);
于 2012-10-03T15:45:46.950 に答える
0

修正しました!

int byteSent = wdll.TRE_send(channel_id, data.toCharArray(), len);

2番目のパラメーターはvoid*ですが、dllコードでは、最初にそれをcharにキャストします*同じタイプを使用しましたが、現在は機能しています。

「TRE_send」はvoid*タイプを必要としているため、これは「一般的な解決策」ではありません...どう思いますか?

さよなら

于 2012-10-04T08:26:23.223 に答える