2016-07-20 1 views
0

JNAを使用してJavaからC++ライブラリにアクセスしようとしています。これを行うには、私が必要とするC++メソッドの周りに薄いラッパーを書きました。ただし、C++オブジェクトをラップし、Javaに渡してC++に戻すと、C++でオブジェクトにアクセスする際に無効なメモリアクセスが発生します。なぜこれが起こっているのかについての指針は非常に役に立つでしょう。JNAでC++オブジェクトを使用する方法

newencoder.h

Class Encoder { 

public: 
Encoder(); 
~Encoder(); 

template<class Type> 
bool originalEncode(Type* input); 

} 

encoder_wrapper.h

typedef void* EncoderWrap; 

    extern "C" { 
    EncoderWrap newEncoder(); 

    const char* encode(EncoderWrap vcEncoder); 
    } 

encoder_wrapper.cpp

#include "encoder_wrapper.h" 
#include "newencoder.h" 

EncoderWrap newEncoder() { 
    return reinterpret_cast<void*>(new Encoder()); 
} 

const char* encode(EncoderWrap encoderObj) { 
     std::string input; 
     (reinterpret_cast<Encoder*>(encoderObj))->originalEncode(&input); //This is where the invalid memory access occurs. Commenting this line and returning a placeholder string does not throw any error. 
     return input.c_str(); 
    } 

JNA私はC++メソッドnewEncoder()内からencode()メソッドを呼び出してみましたし、期待通りにそれが働く

private static class Encoder { 

    public static native Pointer newEncoder(); 
    public static native String encode(Pointer encoderObj); 

    static { 
      Native.setProtected(true); 
      Native.register("encoderlib"); 
    } 

} 

//Code that calls the native methods 

Pointer encoderObj = Encoder.newEncoder(); //Does not fail 
String result = Encoder.encode(encoderObj); //Results in Invalid Memory access 

。このメモリエラーは、Javaでvoid *としてキャストされたエンコーダオブジェクトを受け取り、C++メソッドenocode()に戻すときにのみ発生します。

+0

あなたは_definitely_は 'std :: string'を返すことができません。JNAまで解放されないことが保証されるC文字列(名目上std :: string.c_str())を含むメモリの割り当てブロックを返す必要がありますその内容に基づいてJava Stringを作成する機会があります。 – technomage

+0

メモリが解放されないようにオブジェクトのエンコーディングをオブジェクトに保存することをお勧めします(エンコードを呼び出すたびに再生成されても)。その後、その文字列のC文字列バッファへのポインタを返します。 – technomage

答えて

0

私は構造体にvoid *を入れてJNAに構造体を返すことでこれを解決しました。 newEncoderが呼び出されるたびに、構造体インスタンスが作成され、新しいEncoderオブジェクトがvoid *としてメンバーとしてキャストされます。

structオブジェクトは毎回encode関数に渡されます。このメソッドは、次にvoid *をオブジェクトにキャストして、originalEncodeメソッドを呼び出します。

0

ここにコメントを投稿して申し訳ありませんが、コメントセクションに投稿するのに十分な担当者がいません。

私はCリンケージを持つC++のコードを作成するために使用されるJava JNAのものではなくC++の世界

extern "C" {} 

で多くの経験を持っていません。 encoder_wrapper.hでは、純粋なC++構造のstd :: stringを使用しています。 extern "C"を削除しようとしましたか?

1

Vybzが示唆するように、問題はC++とJNAを混在させることです。 JNAはC++の構造を知らず、純粋なCを期待しています。

つまり、Javaの文字列はstd :: stringと同じであると仮定できません。インタフェースでstd :: stringを使用することはできません。

+0

私はそれがここの問題だとは思わない。文字列をchar *に変更しましたが、エラーは同じ点ではまだ同じです。 – AdityaTS

関連する問題