Хорошо, есть ключевое слово, которое я намеренно скрывал от тегов и заголовка.Это «Android», но это потому, что, хотя проект находится в Android, я не думаю, что мой вопрос имеет какое-либо отношение к нему, и я не хочу пугать людей без опыта в Android.
Итак, обычная проблема с глотком.У меня есть виртуальный метод в классе C ++, который я сделал перегружаемым в Java, добавив в класс функцию director
, и она работает.Проблема заключается в том, что метод получает полиморфный аргумент, который также расширяется на стороне Java, и во время вызова виртуального метода в Java объект поставляется со всей извлеченной полиморфной информацией.
Чтобы представить точную ситуацию;Я пишу игровой движок на C ++ и хочу с удовольствием использовать его на Java.У игрового движка есть класс GameObject
, который регистрирует CollisionListener
с, и когда механизм столкновений обнаруживает событие столкновения, он вызывает метод collidedWith(GameObject & collidee)
всех зарегистрированных collisionListener
с, передавая им объект, с которым они столкнулись.
class CollisionListener {
public:
virtual bool collidedWith(GameObject &){};
~CollisionListener(){} // I know this needs to be virtual but let's forget about that now
};
Я представляю этот класс вместе с классом GameObject
для java, используя следующий файл интерфейса Bridge.i
%module(directors="1") Bridge
%feature("director") CollisionListener;
%include "CollisionListener";
%feature("director") GameObject;
%include "GameObject.h"
Теперь, когда я наследую от CollisionListener
в java и перегрузке collidedWith
, он вызывается с объектом java side GameObject
.Например, если я наследую от класса GameObject
на стороне java и определю класс Bullet
, когда эта пуля сталкивается с другим объектом со слушателем, в вызове метода collidedWith
все, что я получаю, - это GameObject
, так что (object instanceof Bullet)
не работает.Не удивительно, я копался в сгенерированном BridgeJNI.java
и нашел следующее:
public static boolean SwigDirector_CollisionListener_collidedWith(CollisionListener self, long arg0) {
return self.collidedWith(new GameObject(arg0, false));
}
Так что он оборачивает новый объект вокруг указателя перед вызовом java-перегрузок.
Итак,главный вопрос - как получить объект Bullet
при столкновении?
Я нашел способ легко добиться этого, но мне нужно изменить автоматически сгенерированные файлы, что плохоидея.Поэтому я надеюсь, что какой-нибудь мастер swig сможет помочь мне внести изменения в файлы, сгенерированные swig.
Мой маленький взлом состоит в том, чтобы сохранить jobject * self
в каждом объекте C ++ на стороне GameObject
и назначить адресреальный объект Java во время создания реальной стороны Java GameObject
(а не тот, который просто оборачивает указатель).Таким образом, я мог бы определить полиморфный getSelf
метод на стороне C ++ GameObject
и счастливо использовать результат в Java.Есть ли способ внедрить необходимый код в файлы, созданные с помощью swig?
Спасибо
Примечание: Если вы пробовали режиссеры на Android, но они не работали, это потому, что текущая стабильная версия делаетне поддерживаю это.Загрузите Bleeding Edge с сайта Swig.Но я пишу это 22/03/2012, и эта заметка скоро будет ненужной.Причина, по которой деструктор не является виртуальным, заключается в том, что версия Bleeding Edge приводит к аварийному завершению программы в деструкторе, и, по-видимому, из-за того, что деструктор не виртуален, он пока находится под контролем.