Нет необходимости иметь все в одном выражении - возможность цепочки вызовов является просто вопросом удобства (def
и другие функции-члены возвращают ссылку на экземпляр, на котором они были вызваны, чтобы это произошло).
Если проанализировать оператор
main_namespace["Worldb"] = bp::class_<Worldb>("Worldb")
.def("messagewindow", &Worldb::messagewindow)
.def("setnumber", &Worldb::setnumber)
.def("getnumber", &Worldb::getnumber);
, мы увидим, что он последовательно выполняет следующие функции:
- Создает новый экземпляр
class_<Worldb>
- Вызывает функцию-член
def
для предоставления messagewindow
- Вызывает функцию-член
def
для предоставления setnumber
- Вызывает функцию-член
def
дляexpose getnumber
- Назначает его
main_namespace["Worldb"]
.
Мы можем переписать это, чтобы каждая часть была представлена как отдельный оператор следующим образом:
{
bp::class_<Worldb> test_binding = bp::class_<Worldb>("Worldb");
test_binding.def("messagewindow", &Worldb::messagewindow);
test_binding.def("setnumber", &Worldb::setnumber);
test_binding.def("getnumber", &Worldb::getnumber);
main_namespace["Worldb"] = test_binding;
}
Примечание. Мы вводим новую область видимости для ограничения времени жизни test_binding
, которое больше не требуется после назначения.
Сделав это, тривиально представить отдельные методы условно.
Пример кода
#include <boost/python.hpp>
namespace bp = boost::python;
struct test
{
void one() {}
void two() {}
void three() {}
};
int main()
{
Py_Initialize();
try {
bp::object main_module = bp::import("__main__");
bp::object main_namespace = main_module.attr("__dict__");
// Simple bitmap of methods to expose:
// * bit 0 -> one()
// * bit 1 -> two()
// * bit 2 -> three()
uint32_t method_mask(5);
{
// Limit the scope of `test_binding` variable
bp::class_<test> test_binding = bp::class_<test>("test");
if ((method_mask & 1) == 1) {
test_binding.def("one", &test::one);
}
if ((method_mask & 2) == 2) {
test_binding.def("two", &test::two);
}
if ((method_mask & 4) == 4) {
test_binding.def("three", &test::three);
}
main_namespace["test"] = test_binding;
}
exec("print dir(test)\n", main_namespace);
} catch (bp::error_already_set &) {
PyErr_Print();
}
Py_Finalize();
return 0;
}
Консольный вывод
Примечание: Мы ожидаем, что one()
и three()
будут выставлены.Я переформатировал вывод для лучшей читаемости.
['__class__', '__delattr__', '__dict__', '__doc__', '__format__'
, '__getattribute__', '__hash__', '__init__', '__instance_size__'
, '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__'
, '__sizeof__', '__str__', '__subclasshook__', '__weakref__'
, 'one', 'three']
Ссылки