LINUX.ORG.RU

Proxy-пойнтер на объект С++ в питоне, или как обмануть типизацию SWIG

 , ,


2

2

Решил поделиться историей успеха;-)

Про биндинг С++ в Python при помощи SWIG написано довольно много, например тут http://a-iv.ru/pyart/cpp2py.pdf В частности, у SWIG есть неплохая система типизации, поддерживающая в т.ч. перегрузку функций, учитывающая наследование и т.д. - ну почти как в плюсах.

Итак, у нас есть в плюсах что то вроде

class A {...};
void  f(A&);

Мы биндим это в Python через SWIG, и можем в питоне писать

a = A()
f(a)

Теперь мы решили завернуть объект a в питоний класс для каких то надобностей:

class W:
  def __init__(self, ptr): 
    self.__dict__['_ptr'] = ptr
  def __getattr__(self, attr): return getattr(self._ptr, attr)
  def __setattr__(self, attr, value):
    ... # здесь всякое непотребство  
    setattr(self._ptr, attr, value)
...
a = W(A()) 
но теперь мы ес-но уже не можем писать
f(a)
(SWIG ругается что на вход пришел объект не того типа), и мы вынуждены писать
f(a._ptr)
что бывает ну очень неудобно (ломается вся идеология proxy).

Это была длинная преамбула, а теперь амбула - ситуация лечится одной строчкой:

class W:
  def __init__(self, ptr): 
    self.__dict__['_ptr'] = ptr
    self.__dict__['this'] = ptr.this # <== вот эта магия
...
a = W(A()) 
f(a) # все работает

Поле this есть у всех забинденных SWIG-ом классов, и содержит с-но this (плюсовый). Что интересно (почему я это пишу) - оказывается, для навороченной системы типизации SWIG-а ничего кроме этого поля и не нужно, важно что бы экземпляр класса имел правильный this (на объект С++ правильного типа), а его питонье устройство и тип никакого значения не имеют.

★★★★★

Ответ на: комментарий от Deleted

Пожалуйтесь модератору, или проходите мимо. Бай.

AIv ★★★★★
() автор топика

амбула

Как так, а?

anonymous
()

конечно интересно, но если хочется подсунуть свой обьект в эту функцию - то почему просто не написать заодно и враппер этой функции?

def wf(a):
    return f(a._ptr)

anonymous
()
Ответ на: комментарий от anonymous

Можно и так, но это требует больше букофф. Функция может иметь более сложную сигнатуру (хотя враппер можно сделать универсальным, для любой сигнатуры). Этот враппер нужно вызвать для всех функций.

А так вообще ничего делать не надо;-)

AIv ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Зависит от задачи.

AIv ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.