I´m writing an application which is intended to run on different platforms. My base library is written in C++ and I´d like to use SWIG for generating platform-specific code (Java/Android, C#/Windows, Objective C/iOS).
Here I´m using Message-Objects which I´d like to pass from Java -> C++ and from C++ -> Java. The idea is, to have a base type "CoreMessage" and derived messages "StatusMessage", "DebugMessage"...
For me it seems natural to keep the interface generic by doing something like this:
C++:
class CoreMessage {
}
class StatusMessage : public CoreMessage {
public:
string getStatusMessage();
}
class DebugMessage : public CoreMessage {
public:
... some stuff
}
The (bidirectional) interface code in C++ should look like this:
CoreMessage waitForNextMessage(); // Java calls this and blocks until new message is available in a message queue
void processMessage(CoreMessage m); // Java calls this and puts a new message in an eventhandling mechanism
My Swig file is very basic, it simply includes the class-definitions and the interface - nothing else.
Now Swig generates all the classes and interfaces for Java, including the inheritance for the messages in Java:
public class CoreMessage {
...
}
public class StatusMessage extends CoreMessage {
...
}
public class DebugMessage extends CoreMessage {
...
}
The main Java-Module now looks like this:
public native void processMessage(CoreMessage);
public native CoreMessage waitForNextMessage();
When I try to call this code from Java like that:
StatusMessage m = new StatusMessage();
processMessage(m);
this code in C++ will be executed and causes an error:
void processMessage(CoreMessage in) {
StatusMessage* statusPtr = dynamic_case<StatusMessage*>(&in); // works
StatusMessage status = *(statusPtr); // This will cause a runtime error
}
Same problem in the other direction: C++ Code
TsCoreMessage waitForMessage() {
StatusMessage m = StatusMessage();
return m;
}
with this Java Code, calling C++ via JNI and SWIG-generated wrapper:
CoreMessage msg = waitForMessage();
// msg instanceof StatusMessage returns false
StatusMessage s = (StatusMessage) msg; // Causes java.lang.ClassCaseException
So for me it seems JNI looses the type information when passing the object from one language to another...
I did read some threads and articles but I did not find a solution for this - I need a bidirectional solution.
I´m not sure "director" is not what I´m looking for? As far as I understood directors, they are made for classes, extended in java by hand and allow to UP-cast to the corresponding C++ BaseClass... But I´m not sure with my understanding of directors ;-)