2

暗号化機能を実行するために ac ライブラリを呼び出す Java アプリケーションがあります。これは、一部の Java プログラムから使用する必要がある c で実装されたカスタム ライブラリです。Java から bytearray を渡す関数を呼び出し、それを C 関数で符号なし文字ポインタとして扱うことができる SWIG タイプマップを定義する方法が必要です。ここで、c 関数はデータを入力して Java に返します。

私の現在の不幸なインターフェースファイルの抜粋は次のとおりです

%module  CryptoFacade

%pointer_functions(int, intp);
%pointer_functions(unsigned char, unsigned_charp);

int enCrypt(char* clearText, int clearLen,unsigned char* retCipherText, int *retCipherLen);

私の不幸なJavaコードからの抜粋は次のとおりです。以下のコードでは、enCrypt 関数の呼び出しによってバッファが提供されると予想していましたが、生成されたコードに従って「ショート」が提供されます。(コード内のコメントを参照)


class MainLoader {
static {
     System.loadLibrary("dccasecuJ"); //Load my crypto library
}

 public static void main(String[] args) {

 // Define the parameters to be passed by reference 
 SWIGTYPE_p_int retCipherLen=CryptoFacade.new_intp();
 SWIGTYPE_p_unsigned_char retCipherText =
            CryptoFacade.new_unsigned_charp();

CryptoFacade myFacade=new CryptoFacade();   

// Call crypto library function. First two are value parameters, next two are return
myFacade.enCrypt("STRING-TO-ENCRYPT", 17, retCipherText, retCipherLen);

// The length I get back in fourth parameter is just fine 
int gotLen= CryptoFacade.intp_value(retCipherLen); 

//The value I get for the Ciphertext though is a "short" ... no good 
// I need a byte[] in java that has the ciphertext
short gotText= CryptoFacade.unsigned_charp_value(retCipherText);

インターフェイス定義を次のように変更して、3 番目のパラメーターを jbytearray にする必要があると思います。次に、C プログラムの符号なし文字ポインターが指す内容を Java バイト配列にコピーするタイプマップを実装する必要があります。

コンテンツの長さを 256 バイトに指定する必要がある場合は、まったく問題ありません。任意の長さを処理するのは難しい場合があるからです。

誰かがそのようなタイプマップを見つけることができる場所を教えてもらえますか (私は SWIG が初めてで、タイプマップを書いた経験がありません)

%module  CryptoFacade

%pointer_functions(int, intp);
%pointer_functions(unsigned char, unsigned_charp);

int enCrypt(char* clearText, int clearLen, jbyteArray retCipherText, int *retCipherLen);
4

1 に答える 1

1

Java でバイト配列を操作する最も簡単な方法は、%array_class(または%array_functions) を使用することです。これは%pointer_functions、単一の要素だけでなく、配列全体に似ています。このヘッダー ファイルをテストとして使用して、完全な例をまとめました。

inline void foo(unsigned char *bytearr) {
  bytearr[0] = 1;
  bytearr[1] = 2;
  bytearr[2] = 3;
  bytearr[3] = 100;
}

これを SWIG で次のようにラップできます。

%module test

%{
#include "test.h"
%}

%include <carrays.i>
%array_class(unsigned char,ByteArr);

%include "test.h"

// Emit Java code to automatically load the shared library
%pragma(java) jniclasscode=%{
  static {
    try {
        System.loadLibrary("test");
    } catch (UnsatisfiedLinkError e) {
      System.err.println("Native code library failed to load. \n" + e);
      System.exit(1);
    }
  }
%}

また、この機能を実行するためにいくつかの Java をまとめました。

public class run {
  public static void main(String[] argv) {
    ByteArr arr = new ByteArr(4); // Initial size 4
    // You could set some values before passing in if you wanted to.
    test.foo(arr.cast());
    System.out.println(arr.getitem(0) + ", " + arr.getitem(1) + ", " + arr.getitem(2) + ", " + arr.getitem(3));
  }
}

コンパイルして実行しました。unsigned charC または C++ では、Java では次のように表されることに注意してくださいshort。Java には符号なしの型がないため、0 ~ 255 の範囲に収まる最小の型は short です。byteデフォルトではカバーしていません。(他の方法で再マッピングunsigned charしてゲームをプレイすることもできbyteますが、それは直感的ではないため、デフォルトではそうではありません)。

必要に応じて、より高度なことを行うことができます。たとえば、使用できる配列のサイズがわかっている場合は、arrays_java.i . この例では、JNI を使用して型マップを作成し、 の配列を返しunsigned charます。この例は、JNI タイプマップを使用して配列を関数に渡す方法を示しています。(long代わりに を使用していますbyteが、それを変更するには文字通り検索と置換です)。

于 2012-07-19T17:47:27.073 に答える