I am trying to access a C++ library from Java using JNA. To do so I have written a thin wrapper around the C++ methods that I require. However, wrapping the C++ object, passing to Java and back to C++ results in Invalid Memory access while accessing the object in C++. Any pointers on why this is happening will be very helpful.
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
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
I tried calling the encode()
method from within the C++ method newEncoder()
and that works as expected. This memory error only happens when I receive the encoder object casted as void* in java and pass it back to the C++ method enocode()
.
I solved this by enclosing the void* in a structure and returning the structure to JNA. Every time the newEncoder
is called, a structure instance is created which will have a new Encoder object casted as void* as a member.
The struct object is passed to the encode
function every time. This method in turn casts the void* back to the object and calls the originalEncode
method.