Я пишу приложение, предназначенное для работы на разных платформах. Моя базовая библиотека написана на C++, и я хотел бы использовать SWIG для создания кода для конкретной платформы (Java/Android, C#/Windows, Objective C/iOS).Как реализовать общий интерфейс между C++ и Java с помощью SWIG и Downcasts?
Здесь я использую Message-Objects, которые я хотел бы передать из Java -> C++ и из C++ -> Java. Идея заключается в том, чтобы иметь базовый тип «CoreMessage» и производные сообщения «StatusMessage», «DebugMessage» ...
Для меня это кажется естественным сохранить интерфейс родовое делать что-то вроде этого:
C++ :
class CoreMessage {
}
class StatusMessage : public CoreMessage {
public:
string getStatusMessage();
}
class DebugMessage : public CoreMessage {
public:
... some stuff
}
The (двунаправленная) код интерфейса в C++ должен выглядеть следующим образом:
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
Мой файл Swig является очень простой, он просто включает в себя класс-определения и интерфейс - ничего другого.
Теперь Swig генерирует все классы и интерфейсы для Java, в том числе наследования для сообщений в Java:
public class CoreMessage {
...
}
public class StatusMessage extends CoreMessage {
...
}
public class DebugMessage extends CoreMessage {
...
}
Основной Java-модуль теперь выглядит следующим образом:
public native void processMessage(CoreMessage);
public native CoreMessage waitForNextMessage();
Когда я попробуйте называть этот код на Java следующим образом:
StatusMessage m = new StatusMessage();
processMessage(m);
Этот код на C++ будет выполняться пространяется и вызывает ошибку:
void processMessage(CoreMessage in) {
StatusMessage* statusPtr = dynamic_case<StatusMessage*>(&in); // works
StatusMessage status = *(statusPtr); // This will cause a runtime error
}
Та же проблема в другом направлении: C++ код
TsCoreMessage waitForMessage() {
StatusMessage m = StatusMessage();
return m;
}
с этим Java кодекса, вызов C++ через JNI и SWIG сгенерированного обертке:
CoreMessage msg = waitForMessage();
// msg instanceof StatusMessage returns false
StatusMessage s = (StatusMessage) msg; // Causes java.lang.ClassCaseException
Итак, для меня кажется, что JNI теряет информацию о типе при передаче объекта с одного языка на другой ...
Я прочитал некоторые темы и статьи, но я не нашел для этого решения - мне нужно двунаправленное решение.
Я не уверен, что «директор» - это не то, что я ищу? Насколько я понял директоров, они сделаны для классов, расширенных в java вручную и позволяют UP-cast на соответствующий C++ BaseClass ... Но я не уверен в своем понимании директоров ;-)
Если вы создаете класс как тип CoreMessage, то это только тот тип. Однако, если он создан как тип StatusMessage или DebugMessage, то его оба типа и CoreMessage. Можете ли вы привести пример того, что вы пытаетесь выполнить, и где он был создан? – Samhain
Директора действительно нужны, если вы хотите унаследовать от класса на целевом языке. Это звучит так, как вы хотите. – bluedog
Спасибо за ответы! Я отредактировал сообщение, чтобы прояснить мою проблему - так, возможно, у кого-то есть решение? –