1

JNAを使用して、Javaからac関数を呼び出します。この関数は、文字列のリストをユーザー提供のメモリに書き込み、その署名は次のように読み取られます。

void c_getStrings(char *buf, size_t bufSize, char *strings[], size_t *stringsCount)

Java バージョンの場合:

public interface TestCaseDLL extends Library
{
    int c_getStrings(byte[] buf, int bufSize, Memory strings, IntByReference stringCount);
}

public class TestCase
{
    public static void main(String[] args)
    {
        byte[] buf = new byte[100];
        Memory strings = new Memory(Memory.SIZE * 10);
        IntByReference stringCount = new IntByReference(10);

        // c_getStrings() will write the strings continuously to 'buf' and
        // additionally return a list of starting addresses through the
        // 'strings' parameter (that is 'strings' point into 'buf').
        // 'stringCount' holds the initial array size of 'strings' and will
        // return the count of returned strings.
        TestCaseDLL.INSTANCE.c_getStrings(buf, buf.length, strings, stringCount);

        System.out.println(strings.getPointer(0).getString(0));
        System.out.printf("%c\n", buf[0]);  // how can this line change 'strings'?
        System.out.println(strings.getPointer(0).getString(0));

        for (byte b: buf) {
            System.out.print((char) b);
        }
        System.out.println("");
        for (byte b: buf) {
            System.out.printf("%#x ", b);
        }
        System.out.println("");
    }
}

出力

??llo world!
H
?

Hello world! Hallo Welt! Ciao a tutti!
0x48 0x65 0x6c 0x6c 0x6f 0x20 0x77 0x6f 0x72 0x6c 0x64 0x21 0x0 0x48 0x61 0x6c 0x6c 0x6f 0x20 0x57 0x65 0x6c 0x74 0x21 0x0 0x43 0x69 0x61 0x6f 0x20 0x61 0x20 0x74 0x75 0x74 0x74 0x69 0x21 0x0 ...

次の問題が発生しました。

  • 返された文字列が壊れています。「Hello World!」を返す必要があります。「??llo world!」の代わりに
  • 印刷buf[0]すると、返される文字列が変更されます。私はその値を読んでいるだけなので、ここで何が起こっているのかわかりました。

型マッピングが壊れていますか、それとも基本的な何かが欠けていますか?

アップデート

私は今使用を使用します

void c_getStrings(Memory buf, int bufSize, String[] strings, IntByReference stringCount);

やり直す場合は、technomage で提案されているように、2 つの機能に分割します。

void c_fill(char *buf, size_t bufSize);
void c_parseToStringArray(const char *buf, const char *strings[], size_t stringsSize);
4

1 に答える 1

1

最初のいくつかの技術的なポイント:

  • 3 番目の引数は最初の引数を参照するため、プリミティブ配列は使用できません。明示的にネイティブ ポインターを保存するため、NIO バッファーを使用するのは面倒です。それはあなたを残しますMemory。ただし、結果の値だけが必要でString、ポインター自体を気にしない場合は、3 番目の引数が型である場合byte[]、NIO バッファーまたはが機能します。MemoryString[]
  • 3 番目の引数は、書き込み可能なポインターの配列を意図しているようです。Pointer[]またはを使用できますString[]Memory書き込まれるのと同じ数のポインター値を保持するのに十分な大きさが割り当てられている場合は、 を使用することもできます。

次に、より大きな質問:

  • バッファ (おそらく NUL 文字が埋め込まれている) とそのバッファへの個々のポインタの両方が必要なのはなぜですか?
  • JNA からマップすると、JNA が独自の文字列割り当てを行うため、これはばかげているように見えます。String[]プールされた文字列ストレージとしてメモリ バッファを提供するだけの場合は、 3 番目の引数から文字列を取得すると、メモリ バッファは必要ありません。バッファ内のものを操作するつもりなら、そのような変更は「返された」文字列に反映されません。
于 2012-09-26T14:57:37.177 に答える