Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Object Interface

Boost , Boost.Python Tutorial , Boost.Python Tutorial

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Python динамически типизирован, в отличие от C++, который статично типизирован. Переменные Python могут содержать целое число, поплавок, список, дикт, кортеж, стр, длину и т. д., среди прочего. С точки зрения Boost. Python и C++, эти переменные являются примерами класса<object>. В этой главе мы рассмотрим, как обращаться с объектами Python.

Как уже упоминалось, одной из целей Боуста. Python обеспечивает двунаправленное отображение между C++ и Python, сохраняя при этом ощущение Python. Boost.Python C++<object>как можно ближе к Python. Это должно значительно минимизировать кривую обучения.

Класс<object>Обертывание<PyObject*>. Все тонкости работы с<PyObject>, такие как управление подсчетом ссылок, обрабатываются классом<object>. Совместимость объектов C++ бесшовна. Boost.Python C++<object>может быть построено из любого объекта C++.

Чтобы проиллюстрировать этот фрагмент кода Python:

def f(x, y):
     if (y == 'foo'):
         x[3:7] = 'bar'
     else:
         x.items += y(3, x)
     return x
def getfunc():
   return f;

Можно переписать на C++ с помощью Boost. Python работает таким образом:

object f(object x, object y) {
     if (y == "foo")
         x.slice(3,7) = "bar";
     else
         x.attr("items") += y(3, x);
     return x;
}
object getfunc() {
    return object(f);
}

Помимо косметических различий из-за того, что мы пишем код на C++, внешний вид должен быть сразу же очевиден для программиста Python.

Повышаю. Python поставляется с набором производных<object>типов, соответствующих типу Python:

  • список
  • диктовать
  • кортеж
  • полоскание
  • длинный
  • перечислять

Эти производные<object>типы действуют как настоящие типы Python. Например:

str(1) ==> "1"

Там, где это уместно, конкретный производный<object>имеет соответствующие методы типа Python. Например,<dict>имеет<keys()>метод:

d.keys()

<make_tuple>предусмотрено декларированиекортежных букв. Пример:

make_tuple(123, 'D', "Hello, World", 0.0);

В C++, когда Boost.Python<object>s используются в качестве аргументов для функций, требуется сопоставление подтипов. Например, когда функция<f>, как указано ниже, обернута, она будет принимать только экземпляры типа и подтипов Python<str>.

void f(str name)
{
    object n2 = name.attr("upper")();   // NAME = name.upper()
    str NAME = name.upper();            // better
    object msg = "%s is bigger than %s" % make_tuple(NAME,name);
}

Более подробно:

str NAME = name.upper();

Иллюстрирует, что мы предоставляем версии методов типа Стр в качестве функций C++.

object msg = "%s is bigger than %s" % make_tuple(NAME,name);

Показывает, что вы можете написать эквивалент C++<"format" % x,y,z>на Python, что полезно, поскольку нет простого способа сделать это в std C++.

Python:

>>> d = dict(x.__dict__)     # copies x.__dict__
>>> d['whatever'] = 3        # modifies the copy

C++:

dict d(x.attr("__dict__"));  // copies x.__dict__
d['whatever'] = 3;           // modifies the copy

class_<T> as objects

Из-за динамичного характера Boost. Объекты Python, любой<class_<T>>также может быть одним из этих типов! Следующий фрагмент кода обертывает объект класса (типа).

Мы можем использовать это для создания завернутых экземпляров. Пример:

object vec345 = (
    class_<Vec2>("Vec2", init<double, double>())
        .def_readonly("length", &Point::length)
        .def_readonly("angle", &Point::angle)
    )(3.0, 4.0);
assert(vec345.attr("length") == 5.0);

В какой-то момент нам нужно будет получить значения C++ из экземпляров объектов. Этого можно достичь с помощью функции<extract<T>>. Рассмотрим следующее:

double x = o.attr("length"); // compile error

В коде выше мы получили ошибку компилятора, потому что Boost. Python<object>не может быть преобразован в<double>. Вместо этого, то, что мы хотели сделать выше, может быть достигнуто путем написания:

double l = extract<double>(o.attr("length"));
Vec2& v = extract<Vec2&>(o);
assert(l == v.length());

Первая линия пытается извлечь «длинный» атрибут Boost. Python<object>. Вторая линия пытаетсяизвлечь<Vec2>объект из удерживаемого Boost. Python<object>.

Обратите внимание, что мы сказали «попытка» выше. Что, если буст. Python<object>не поддерживает тип<Vec2>? Это, безусловно, возможно, учитывая динамическую природу Python<object>. Чтобы быть на безопасной стороне, если тип C++ не может быть извлечен, бросается соответствующее исключение. Чтобы избежать исключения, нужно проверить на экстрактивность:

extract<Vec2&> x(o);
if (x.check()) {
    Vec2& v = x(); ...

Проницательный читатель мог заметить, что<extract<T>>объект на самом деле решает проблему непостоянного копирования:

dict d = extract<dict>(x.attr("__dict__"));
d["whatever"] = 3;          // modifies x.__dict__ !

Повышаю. Python имеет отличную возможность захватывать и обертывать C++ enums. В то время как Python не имеет<enum>типа, мы часто хотим представить наши C++ перечни Python как<int>. Повышаю. Средство перечня Python упрощает эту задачу, одновременно заботясь о правильном преобразовании динамической типизации Python в сильную статичную типизацию C++ (в C++ инты не могут быть неявно преобразованы в перечни). Чтобы проиллюстрировать, приведем список C++:

enum choice { red, blue };

Конструкция:

enum_<choice>("choice")
    .value("red", red)
    .value("blue", blue)
    ;

Его можно использовать для работы с Python. Новый тип enum создается в текущем<scope()>, который обычно является текущим модулем. Сниппет выше создает класс Python, полученный из типа Python<int>, который связан с типом C++, переданным в качестве его первого параметра.

[Note] Note

Что такое масштаб?

Область действия - это класс, который имеет связанный глобальный объект Python, который управляет пространством имен Python, в котором новые классы расширений и обернутые функции будут определены как атрибуты. Подробности можно найти здесь.

Вы можете использовать эти значения в Python.

>>> my_module.choice.red
my_module.choice.red

где my_module - модуль, в котором декларируется число. Вы также можете создать новую область вокруг класса:

scope in_X = class_<X>("X")
                .def( ... )
                .def( ... )
            ;
// Expose X::nested as X.nested
enum_<X::nested>("nested")
    .value("red", red)
    .value("blue", blue)
    ;

Если вы хотите, чтобы<boost::python::object>управлял указателем на<PyObject*>пиобдж, вы делаете:

boost::python::object o(boost::python::handle<>(pyobj));

В этом случае<o>объект, управляющий<pyobj>, выигрывает’t увеличение эталонного счета на строительство.

В противном случае использовать заимствованную ссылку:

boost::python::object o(boost::python::handle<>(boost::python::borrowed(pyobj)));

В этом случае<Py_INCREF>называется, поэтому<pyobj>не разрушается, когда объект выходит из сферы действия.


PrevUpHomeNext

Статья Object Interface раздела Boost.Python Tutorial Boost.Python Tutorial может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Boost.Python Tutorial ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 18:44:56/0.010470867156982/1