используя boost.python, как расширить функцию класса __dir__? - PullRequest
0 голосов
/ 28 июня 2018

У меня есть класс, экспортированный в python, в чистом python я могу легко расширить функцию dir следующим образом:

 def __dir__(self):
    attr = list(self.__attributesMap().keys())
    return attr + dir(type(self))

поэтому я добавил функцию dir в мой класс c ++, но вопрос в том, как получить значение dir(type(self)) в c ++ с boost.python?

1 Ответ

0 голосов
/ 29 июня 2018

К сожалению, я не думаю, что это возможно. Мы могли бы частично объявить класс:

struct test {
    void foo() { printf("foo!\n"); }
    void bar() { printf("bar!\n"); }
    void baz() {}
};

// define initial tclass
auto tclass = class_<test>("test")
    .def("foo", &test::foo)
    .def("bar", &test::bar);

А затем расширить функцию dir :

auto cur = tclass();
tclass.def("__dir__",
    make_function(
        [cur] (object) -> object {
            list curdir = (list)object(handle<>(PyObject_Dir(cur.ptr())));
            curdir.append("hello");
            return curdir;
        },
        default_call_policies(),
        boost::mpl::vector<object, object>()));

Но, делая это таким образом, используя экземпляр самого объекта, мы получаем бесконечный цикл, потому что он просто перепривязывает внутренние указатели. И если мы попытаемся вызвать PyObject_Type и вызвать PyObject_Dir для этого, мы получим Boost.Python.class обратно, так как это фактический тип классов представления boost :: python, и к нему не добавлены правильные объекты ( как это делается динамически).

Мы можем увидеть это, если посмотрим на python:

>>> dir(skunk.test)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__instance_size__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'foo']

>>> dir(type(skunk.test))
['__abstractmethods__', '__base__', '__bases__', '__basicsize__', '__call__', '__class__', '__delattr__', '__dict__', '__dictoffset__', '__doc__', '__eq__', '__flags__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__instancecheck__', '__itemsize__', '__le__', '__lt__', '__module__', '__mro__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasscheck__', '__subclasses__', '__subclasshook__', '__weakrefoffset__', 'mro']

Тип класса не тот, который нам нужен. Таким образом, вы не можете использовать сам класс (бесконечный цикл) и не можете использовать тип (не тот тип, который мы привыкли в Python), что осталось? Возможно, вы сможете определить класс дважды и использовать один, чтобы прокормить каталог другого, но это кажется излишним. Лучше просто вручную написать функцию dir, чтобы жестко закодировать другие методы класса. Вы должны вручную .def () их в любом случае.

...