16891


以下のコードをSWIG3を使用してclass Foo を Javaで使用できるようにしたいとしています。  
元のC++コードは以下のようになっています。  
C++側のコードは変更することはできないとします。

[code]

    class Foo {
     public:
       static Foo* getFoo(return &_Foo;}
       /* some method */
     };
     static Foo _Foo;
    
[/code]

これをJavaで

[code]

     Foo _foo = Foo.getFoo();
    
[/code]

とします。  
SWIG3はそのまま_Fooをreturnするコードを出力しますが、  
にしてもclass FooはJavaのObjectから継承されていないので  
Exceptionになります。

[code]

     java.lang.Error: Unresolved compilation problems: 
        The type java.lang.Object cannot be resolved.
    
[/code]

ではSWIGにたよらず自力でJNIを作成するとしても  
すでにstaticなオブジェクトがあるわけですから、JNIEnv：：NewObject（）で新規オブジェクトを  
つくることもできません。  
staticですからガーベジコレクション時の挙動も謎です。

どのようにしてstaticオブジェクトを返せば良いのでしょうか？  
やはり、不可能なのでしょうか。


CC BY-SA 3.0
2015-09-15T01:48:23.893
16614
2015-09-24T07:37:13.847
7844
question
java c++ jni
staticなオブジェクトをSWIG, JNIでreturnするにはどうすればよいでしょうか


>
> C++のクラスオブジェクトをJavaの世界から直接扱うことは出来ないため、両者の"対応付け"を行うコードをJNIで書く‌​ことになります。C++側がシングルトンなのであれば、Java側にもシングルトン的な動きをするラッパーを用意するのが素直な（≒力技）実装です。

上記をそのまま実装したコードです。（期待されるスマートな解法からは程遠いと思われます...）

[code]

    // C++コード: FooImpl.cpp/h
    class Foo {
    public:
      static Foo* getFoo() { return &_Foo; }
      int someMethod() { /*...*/ }
    };
    static Foo _Foo;
    
[/code]

Java側のラッパークラス`FooWrapper`を用意します。ここでは`native`メソッドを`static`にしています。最終的にはC++側シングルトン・インスタンスのメンバ関数呼び出しを行うため、Java側APIは`static`メソッドにしても意味論上は等価という考え方に基づきます。

[code]

    // Javaコード: FooWrapper.java
    package com.example;
    
    public class FooWrapper {
      public static native int someMethod();
      static { System.loadLibrary("FooWrapper"); }
    }
    
[/code]

上記`FooWrapper.java`を元に、`javah`ツールを用いてC/C++用ヘッダファイル`com_example_FooWrapper.h`を生成します。

[code]

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_example_FooWrapper */
    // [...]
    /*
     * Class:     com_example_FooWrapper
     * Method:    someMethod
     * Signature: ()I
     */
    JNIEXPORT jint JNICALL Java_com_example_FooWrapper_someMethod
      (JNIEnv *, jclass);
    // [...]
    
[/code]

JNIブリッジ層では自動生成`com_example_FooWrapper.h`の関数群を実装し、`FooImpl.h`にある本体コードを呼び出します。

[code]

    // JNIブリッジコード: FooWrapper.cpp
    #include "com_example_FooWrapper.h"
    #include "FooImpl.h"
    
    JNIEXPORT jint JNICALL Java_com_example_FooWrapper_someMethod(JNIEnv *, jclass)
    {
      return static_cast<jint>(Foo::getFoo()->someMethod());
    }
    
[/code]


CC BY-SA 3.0
2015-09-24T05:40:42.973
16891
2015-09-24T07:37:13.847
2015-09-24T07:37:13.847
49
49
16614
answer