2

次の3つのファイルがあります。

sab1.hpp:

class CRectangle 

{
    int x, y;

public:
    void set_values (int,int);
    void print(char **db);
    int area ();
};

sab1.cpp:

#include <iostream>
#include "sab1.hpp"
using namespace std;

int CRectangle::area () 
{
    return (x*y);
}

void CRectangle::set_values (int a, int b) 
{
    x = a;
    y = b;
}

void CRectangle::print(char **db) 
{
    cout <<db[0];
}

int main () 
{
    CRectangle rect;
    char *a[] = {"Hi", "bye" }  ;

    rect.set_values (3,4);
    cout << "area: " << rect.area();
    rect.print(&a[0]);
    return 0;
}

sab1.i:

%module Rec
%{
/* Includes the header in the wrapper code */
#include "sab1.hpp"
%}
class CRectangle {
    int x, y;
public:
    void set_values (int,int);
    void print(char **db);
    int area ();
};

次の通常のコマンドを使用して、さまざまな中間ファイルを作成します。

1) swig -c++ -java sab1.i

2) g++ -fpic -c sab1.cpp sab1_wrap.cxx -I /usr/lib/jvm/java-6-openjdk-i386/include/ -I /usr/lib/jvm/java-6-openjdk-i386/include /linux/

次に、これを使用して共有ライブラリを作成します: g++ --shared sab1.o sab1_wrap.o -o libegs.so

次に、C++ クラスの関数にアクセスするための次の Java ファイルを作成します。

public class Test 
{
    public static void main(String args[]) 
    {
        System.loadLibrary("egs");
        CRectangle a = new CRectangle();
        a.set_values(4,5);
        System.out.println(a.area());
        a.print("Hi");
    }
}

Java ファイル (javac -classpath . Test.java ) をコンパイルすると、次のエラーが発生します。

Test.java:17: print(SWIGTYPE_p_p_char) in CRectangle cannot be applied to (java.lang.String)  a.print("Hi");
 ^

では、Java コードに char ** 変数を理解させるにはどうすればよいでしょうか。SWIG インターフェイス ファイル (sab1.i) でタイプマップを作成しようとしましたが、正しく理解できません。

助けてくれてありがとう。

4

1 に答える 1

4
%module Rec
%include "various.i"

%apply char **STRING_ARRAY { char **db }

%include "sab1.hpp"

リンク先のファイルvarious.iはこのように動作するはずです。プロジェクトのインクルード ディレクトリまたは SWIG インクルード パス内の SWIG が見つけられる場所に置くだけです。

%include代わりに使用#include "sab1.hpp"すると、ラップしたいクラスの定義をコピーする必要がなくなります。このディレクティブは、名前が の typeのすべての引数に%applytypemap from を適用します。ラップしたい他の引数名がある場合は、次のように追加します。various.ichar**db

%apply char **STRING_ARRAY { char **db, char **foo, char **bar }

タイプのすべての引数をラップしたいだけならchar**(安全ではありません!)、単に名前を省略してください:

%apply char **STRING_ARRAY { char ** }

StringC++ コードでは、配列に 2 つの文字列が含まれることが想定されているため、Java から2 つ以上の s の配列を渡す限り問題ありません。typemap は 3 番目の null ポインターを配列に追加しますが、C++ コードは気付かないでしょう。2 未満の配列を渡すとString、C++ コードがクラッシュする可能性があります。

ラップしている C++ 関数のいずれかが文字列の配列も返す場合は、問題が発生しています。SWIG はそれらを Java 配列に変換しようとしますが、配列内の 3 番目の要素を探すときにクラッシュする可能性があります (null ポインターが見つかるまで要素を探し続けます)。戻り値を破棄しても構わない場合は、次のようにすることができます。

%module Rec
%include "various.i"

%typemap(jni)     char **db = char **STRING_ARRAY;
%typemap(jtype)   char **db = char **STRING_ARRAY;
%typemap(jstype)  char **db = char **STRING_ARRAY;
%typemap(in)      char **db = char **STRING_ARRAY;
%typemap(freearg) char **db = char **STRING_ARRAY;
%typemap(javain)  char **db = char **STRING_ARRAY;

%include "sab1.hpp"

これは、入力引数を扱う typemap の部分にのみ適用されます。

于 2012-09-06T18:28:34.647 に答える