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()
に戻すときにのみ発生します。
あなたは_definitely_は 'std :: string'を返すことができません。JNAまで解放されないことが保証されるC文字列(名目上std :: string.c_str())を含むメモリの割り当てブロックを返す必要がありますその内容に基づいてJava Stringを作成する機会があります。 – technomage
メモリが解放されないようにオブジェクトのエンコーディングをオブジェクトに保存することをお勧めします(エンコードを呼び出すたびに再生成されても)。その後、その文字列のC文字列バッファへのポインタを返します。 – technomage