python pyqt boost-python python-sip

Python método de resolución de misterio



pyqt boost-python (3)

No puedo entender por qué este programa está fallando.

#!/usr/bin/env python from __future__ import division, print_function from future_builtins import * import types import libui as ui from PyQt4 import QtCore import sip p = ui.QPoint() q = QtCore.QPoint() def _q_getattr(self, attr): print("get %s" % attr) value = getattr(sip.wrapinstance(self.myself(), QtCore.QPoint), attr) print("get2 %s returned %s" % (attr, value)) return value p.__getattr__ = types.MethodType(_q_getattr, p) print(p.__getattr__(''x'')()) # Works! Prints "0" print(p.x()) # AttributeError: ''QPoint'' object has no attribute ''x''

Usé Boost.Python para crear libui, que expone la clase QPoint. También incluí PyQt4, que tiene un QPoint expuesto a sorbos. Estoy tratando de lograr un mapeo entre los dos tipos.

Comprobé que p es una clase de nuevo estilo, ¿por qué no se llama a __getattr__ para px() ?


Este es un ejemplo de cómo integrar PyQt4 y boost :: python

En primer lugar, debemos definir la función envolver / desenvolver para tratar con indicadores simples

long int unwrap(QObject* ptr) { return reinterpret_cast<long int>(ptr); } template <typename T> T* wrap(long int ptr) { return reinterpret_cast<T*>(ptr); }

después de eso debemos registrar todas las clases que queremos integrar a

class_<QObject, QObject*, boost::noncopyable>("QObject", no_init) .def("unwrap", unwrap) .def("wrap", make_function( wrap<QObject>, return_value_policy<return_by_value>() )) .staticmethod("wrap"); class_<QWidget, bases<QObject>, QWidget*, boost::noncopyable>("QWidget") .def("wrap", make_function( wrap<QWidget>, return_value_policy<return_by_value>() )) .staticmethod("wrap"); class_<QFrame, bases<QWidget>, QFrame*, boost::noncopyable>("QFrame") .def("wrap", make_function( wrap<QFrame>, return_value_policy<return_by_value>() )) .staticmethod("wrap"); class_<QLabel, bases<QFrame>, QLabel*, boost::noncopyable>("QLabel") .def("wrap", make_function( wrap<QLabel>, return_value_policy<return_by_value>() )) .staticmethod("wrap");

y por ejemplo, tenemos una clase que funciona con ... QLabel:

class worker: public QObject { ... void add_label(QLabel*); };

también debemos exponer esta clase a python:

class_<worker, bases<QObject>, worker*, boost::noncopyable>("worker") .def("add_label", &worker::add_label);

ahora estamos listos para la interacción, en C ++ - tamaño haga algo como esto

worker* w = new worker; main_namespace["worker"] = boost::ref(w);

pitón:

from PyQt4.Qt import * import sip import mylib as MyLib #... #If you are using QApplication on C++-size you don''t need to create another one lb = QLabel("label from PyQt4!") lb_ptr = sip.unwrapinstance(f) my_lb = MyLib.QLabel.wrap(lb_ptr) worker.add_label(my_lb)

En otro caso, si no le envía su propio Q-objeto a PyQt4:

QLabel* lb = new QLabel("C++ label"); main_namespace["lb"] = boost::ref(lb);

pitón:

from PyQt4.Qt import * import sip import mylib as MyLib #... my_lb_ptr = lb.unwrap() qt_lb = sip.wrapinstance(my_lb_ptr, QLabel)

Y este es mi verdadero pequeño ayudante:

from PyQt4.Qt import * import sip def toQt(object, type): ptr = object.unwrap() return sip.wrapinstance(ptr, type) def fromQt(object, type): ptr = sip.unwrapinstance(object) return type.wrap(ptr)


Sugiero que no intentes exponer QPoint en boost python. Debería poder registrar convertidores desde / hacia python con boost que usará las funciones de API SIP para convertir QPoint de / a python como los objetos sip.

Lo hice, pero no lo suficiente como para dar más detalles.


Esto es algo similar al problema que alguien más ha encontrado ayer. En resumen, parece que los métodos especiales (como __getattr__ , __str__ , __repr__ , __call__ y demás) no son reemplazables en la instancia de clase de nuevo estilo, es decir, solo puede definirlos en su tipo.

Y aquí hay una adaptación de mi solución para ese problema que debería funcionar para usted:

def _q_getattr(self, attr): print("get %s" % attr) return getattr(self, ''x'') def override(p, methods): oldType = type(p) newType = type(oldType.__name__ + "_Override", (oldType,), methods) p.__class__ = newType override(p, { ''__getattr__'': _q_getattr}) print(p.__getattr__(''x'')()) # Works! Prints "0" print(p.x()) # Should work!