объект Python на нативный указатель c ++ - PullRequest
2 голосов
/ 31 августа 2009

Мне нравится идея использовать python в качестве встроенного языка сценариев для проекта, над которым я работаю и у которого большинство вещей работает. Однако я не могу преобразовать расширенный объект Python обратно в собственный указатель C ++.

Итак, это мой класс:

class CGEGameModeBase
{
public:
    virtual void FunctionCall()=0;
    virtual const char* StringReturn()=0;
};

class CGEPYGameMode : public CGEGameModeBase, public boost::python::wrapper<CGEPYGameMode>
{
public:
    virtual void FunctionCall()
    {
        if (override f = this->get_override("FunctionCall"))
            f();
    }

    virtual const char* StringReturn()
    {
        if (override f = this->get_override("StringReturn"))
            return f();

        return "FAILED TO CALL";
    }
};

Поверхностная упаковка:

BOOST_PYTHON_MODULE(GEGameMode)
{
    class_<CGEGameModeBase, boost::noncopyable>("CGEGameModeBase", no_init);

    class_<CGEPYGameMode, bases<CGEGameModeBase> >("CGEPYGameMode", no_init)
        .def("FunctionCall", &CGEPYGameMode::FunctionCall)
        .def("StringReturn", &CGEPYGameMode::StringReturn);
}

и код питона:

import GEGameMode

def Ident():
    return "Alpha"

def NewGamePlay():
    return "NewAlpha"


def NewAlpha():
    import GEGameMode
    import GEUtil

    class Alpha(GEGameMode.CGEPYGameMode):
        def __init__(self):
            print "Made new Alpha!"

        def FunctionCall(self):
            GEUtil.Msg("This is function test Alpha!")

        def StringReturn(self):
            return "This is return test Alpha!"

    return Alpha()

Теперь я могу нормально вызывать первые функции, выполняя это:

const char* ident = extract< const char* >( GetLocalDict()["Ident"]() );
const char* newgameplay = extract< const char* >( GetLocalDict()["NewGamePlay"]() );

printf("Loading Script: %s\n", ident);
CGEPYGameMode* m_pGameMode = extract< CGEPYGameMode* >( GetLocalDict()[newgameplay]() );

Однако, когда я пытаюсь преобразовать класс Alpha обратно в его базовый класс (последняя строка выше), я получаю ошибку повышения:

TypeError: No registered converter was able to extract a C++ pointer to type class CGEPYGameMode from this Python object of type Alpha

Я много занимался поиском в сети, но не могу понять, как преобразовать объект Alpha в указатель его базового класса. Я мог бы оставить его как объект, но вместо этого иметь его как указатель, чтобы его мог использовать некоторый код, не поддерживающий Python. Есть идеи?

Ответы [ 3 ]

2 голосов
/ 31 августа 2009

Благодаря Стефану из списка рассылки python c ++, мне не хватало

super(Alpha, self).__init__()

из вызова конструктора, означающего, что он никогда не создавал родительский класс. Думал, что это было бы автоматически: D

Единственной проблемой, с которой я столкнулся, было сохранение нового экземпляра класса в качестве глобальной переменной, в противном случае он очищался по мере выхода из области видимости.

Так счастлив теперь

0 голосов
/ 31 августа 2009

Может быть не тот ответ, который вы ищете, но посмотрите на ChaiScript для встраивания в ваше приложение C ++.

По данным их сайта,

ChaiScript - первый и единственный язык сценариев разработан с с C ++ совместимостью в разум. Это ECMAScript-вдохновленный, встроенный функционально-подобный язык.

У ChaiScript нет метакомпилятора, нет библиотечные зависимости, нет системы сборки требования и отсутствие наследственного багажа любой. Может работать без проблем с любые функции C ++, которые вы ему предоставляете. Это не должно быть сказано явно о любом типе, это функция центричен.

С ChaiScript вы можете буквально начать сценарий вашего приложения добавив три строки кода к вашему программа, а не изменение вашей сборки шаги на всех.

0 голосов
/ 31 августа 2009

Ну, я не уверен, поможет ли это вам, но у меня была такая же проблема со скриптами в Lua. Мы создали объекты из Lua и хотели, чтобы некоторый код на C ++ обрабатывал объекты с помощью указателей. Мы сделали следующее:

  • весь объектный материал был написан на c ++, включая конструкторы, деструкторы и фабричный метод;
  • Код lua вызывал фабричный метод для создания объекта. этот фабричный метод 1) дал объекту уникальный идентификационный номер и 2) зарегистрировал его в карте c ++, которая сопоставила идентификационные номера с собственными указателями;
  • поэтому, всякий раз, когда lua собирался передать указатель на код c ++, он вместо этого давал идентификатор объекта, и код c ++ просматривал карту для поиска фактического указателя по идентификатору.
...