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

Chapter 8. Topics

Boost , Boost.Python Reference Manual , Boost.Python Reference Manual

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

Chapter 8. Topics

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

f("tea", 4, 2) // In Python: f('tea', 4, 2)

И, конечно, способ<object>экземпляра<x>может быть вызван с помощью оператора вызова функции соответствующего атрибута:

x.attr("tea")(4, 2); // In Python: x.tea(4, 2)

Если у вас нет<object>пример,<Boost.Python>предоставляет два семейства шаблонов функций,<call>и<call_method>для вызова функций и методов Python соответственно на<PyObject*>. Интерфейс вызова объекта функции Python (или любого объекта, который можно назвать Python) выглядит следующим образом:

call<ResultType>(callable_object, a1, a2... aN);

Назвать метод объекта Python также легко:

call_method<ResultType>(self_object, "method-name", a1, a2... aN);

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

Аргументы преобразуются в Python по их типу. По умолчанию аргументы<a1...aN>копируются в новые объекты Python, но это поведение может быть отменено использованием<ptr()>и<ref()>:

class X : boost::noncopyable
{
   ...
};
void apply(PyObject* callable, X& x)
{
   // Invoke callable, passing a Python object which holds a reference to x
   boost::python::call<void>(callable, boost::ref(x));
}

В таблице ниже x обозначает фактический объект аргументации, а cv обозначает необязательную квалификацию cv: «const», «volatile» или «const volatile».

Тип аргумента

поведение

<Tcv &><T cv>

Аргумент Python создается теми же средствами, которые используются для возвращаемого значения обернутой функции C++, возвращающей T. Когда T является типом класса, это обычно означает, что x копируется в новый объект Python.

Т*

Если x == 0, то аргумент Python не будет ничьим. В противном случае аргумент Python создается теми же средствами, которые используются для возвращаемого значения обернутой функции C++, возвращающей T. Когда T является типом класса, это обычно означает, что x копируется в новый объект Python.

boost::reference_wrapper

Аргумент Python содержит указатель, а не копию x.get(). Примечание: неспособность гарантировать, что ни один код Python не содержит ссылки на полученный объект после срока службы *x.get() может привести к сбою!

pointer_wrapper

Если x.get() == 0, аргументом Python будет No. В противном случае аргумент Python содержит указатель, а не копию *x.get(). Примечание: неспособность гарантировать, что ни один код Python не содержит ссылки на полученный объект после срока службы *x.get() может привести к сбою!

В целом<call<ResultType>()>и call_method() возвращают результат Тип путем использования всех конвертеров lvalue и rvalue от_python, зарегистрированных для ResultType, и возврата копии результата. Однако, когда ResultType является указателем или эталонным типом, Boost. Python ищет только конвертеры lvalue. Чтобы предотвратить висячие указатели и ссылки, будет выброшено исключение, если объект результата Python имеет только одно количество ссылок.

В общем, чтобы получить аргументы Python, соответствующие a1...aN, для каждого должен быть создан новый объект Python; должен ли объект C++ быть скопирован в этот объект Python или объект Python просто должен содержать ссылку / указатель на объект C++? В общем, последний подход небезопасен, так как называемая функция может где-то хранить ссылку на объект Python. Если объект Python будет использоваться после уничтожения объекта C++, мы разрушим Python.

В соответствии с философией, согласно которой пользователям на стороне Python не нужно беспокоиться о сбое интерпретатора, поведение по умолчанию заключается в копировании объекта C++ и разрешении некопирующего поведения только в том случае, если пользователь пишет boost::ref(a1) вместо a1 напрямую. По крайней мере, таким образом, пользователь не получает опасное поведение «случайно». Также стоит отметить, что поведение без копирования («посредством ссылки») в целом доступно только для типов классов и не будет работать во время выполнения с исключением Python, если используется иначе.

Тем не менее, типы указателей представляют проблему: один из подходов заключается в отказе от компиляции, если какой-либо AN имеет тип указателя: в конце концов, пользователь всегда может пройти * AN, чтобы пройти «по значению» или ref (* AN), чтобы указать на поведение ссылки. Тем не менее, это создает проблему для ожидаемого нулевого указателя на преобразование «Никто»: незаконно отменять значение нулевого указателя.

Компромисс, на котором я остановился, таков:

  1. Поведение по умолчанию является пассивным. Если вы пройдете ненулевой указатель, указатель будет скопирован в новый объект Python; в противном случае соответствующий аргумент Python не будет ничьим.
  2. Если вы хотите пошаговое поведение, используйте ptr(aN), если aN является указателем, и ref(aN) в противном случае. Если нулевой указатель передается в ptr(aN), соответствующий аргумент Python не будет ничьим.

Что касается результатов, у нас есть аналогичная проблема: если ResultType разрешено быть указателем или эталонным типом, срок службы объекта, на который он ссылается, вероятно, управляется объектом Python. Когда этот объект Python разрушается, наш указатель свисает. Проблема особенно плоха, когда ResultType является char const* - соответствующий объект Python String обычно однозначно упоминается, что означает, что указатель свисает, как только Call(...) возвращается.

Старый буст. Python v1 решает эту проблему, отказываясь компилировать любое использование call(), но это заходит слишком далеко и недостаточно далеко. Это заходит слишком далеко, потому что есть случаи, когда собственный объект строки Python выживает за пределами вызова (например, когда это имя класса Python), и это не заходит достаточно далеко, потому что у нас может быть такая же проблема с обратным указателем или ссылкой любого другого типа.

В Росте. Python этим занимается:

  1. Снятие ограничения по времени компиляции на<char const*>возврат обратного вызова
  2. Обнаружение случая, когда ссылка рассчитывает на результат, объект Python равен 1 и бросание исключения внутри<call<U>(...)>, когда<U>является указателем или эталонным типом.

Это должно быть приемлемо безопасным, потому что пользователи должны четко указать указатель / ссылку для<U>в<call<U>>, и они будут защищены от болтовни во время выполнения, по крайней мере, достаточно долго, чтобы выйти из вызова<call<U>(...)>.


PrevUpHomeNext

Статья Chapter 8. Topics раздела Boost.Python Reference Manual Boost.Python Reference Manual может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Boost.Python Reference Manual ::


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 02:09:35/0.027389049530029/1