javaでは、JNAを使用してVC ++ dllファイルをロードし、その中の関数を呼び出しています。1つの関数では、6つのパラメーターを送信する必要があります。VC++関数の定義では、最初の3つのパラメーターの正しい値を取得していますが、最後の3つのパラメーターの値は「0」です。
2番目のパラメーターはバイト配列です。1024バイトを送信すると、5番目のboolパラメーターがfalseとして取得されますが、10バイトを渡すと、関数プロトタイプがtrue と見なされます。パラメーターのサイズに応じてマッピングが変更されますか?
または、JNAスタックが小さすぎて、6つのパラメーターを保持できませんか?しかし、JNAのドキュメントによると、クラス値は256であるため、6つのパラメーターの数は問題ではないと思います。int deviceupload(Pointer p, _byte[] data_, long startaddress, long datalength,_Boolean rt_,Pointer xyz);
MAX_NARGS
Function
3番目と4番目のパラメーターのデータ型が同じでも、VC ++では関数定義startaddress
は正しく受信されますが、datalength
受信された値は0
なので、なぜこれほど奇妙な動作をしているのでしょうか。
2 に答える
実際に私の問題は解決しました、VC ++関数は4バイトのlongを期待していましたが、javaでは8バイトのlongを渡していましたが、JNAのドキュメントによると、 VC ++のlongに相当するものはjavaのNativeLongですが、2つのNativeLong変数を減算することはできません私はそれをすることになっているので、私はロングを通過していました。
しかし、後でVC ++の(4bytes)パラメーターint
に対してjavaで(4bytes)引数を渡した後、正しく機能しましたが、変数データ型のミスマッチ変数データが原因で、以前のパラメーターデータ型のミスマッチが原因で他のパラメーターが影響を受けた理由を理解しました影響を受けているので、まだ私の質問は答えられていません、誰かが私がそれを理解するのを手伝ってくれるでしょうか?、残念ながら私のエラーだけがクリアされましたlong
startaddress
datalength
引数は、スタック上のメモリ「スロット」に配置されます。小さな引数は1つのスロットを使用するか、別の引数とスロットを共有する場合がありますが、大きな引数は2つのスロットを使用する場合があります。小さな引数を大きな引数と間違えると、後続のすべての引数が誤った位置にシフトすることがわかります。
void my_func(int32 p1、int64 p2)
| |
+---------------+
| P2 (64-bit) |
+---------------+
| P2 | (P2 takes up two slots)
+---------------+
+ P1 (32-bit) |
+---------------+ <-- Top of stack
これで、誤ってP1に64ビット値を使用した場合、代わりに次のようになります。
| |
+---------------+
| P2 (64-bit) |
+---------------+
| P2 |
+---------------+
+ P1 (64-bit) |
+---------------+
+ P1 |
+---------------+ <-- Top of stack
呼び出し先(呼び出した関数)は、このシフトが発生したことを認識していないため、予想される位置から引数を読み取ろうとします。小さな引数の場合は大きな引数の一部を取得する可能性があり、大きな引数の場合は2つ以上の他の引数の一部を取得する可能性があります。
呼び出し先が実際に見るのはこれです:
| |
+---------------+
| (P2) |
+---------------+
+ (P1) |
+---------------+
+ (P1) |
+---------------+ <-- Top of stack
P1で読み取られた値は、実際には大きい方の値の半分にすぎないのに対し、P2で読み取られた値は、P1の残りの半分とP2として渡された値の半分で構成されていることがわかります。
(この説明はやや簡略化されていますが、一般的にスタックがどのように機能するかを示しています)