在PyQT和Boost.Python间共享小部件

5 投票
1 回答
1159 浏览
提问于 2025-04-15 14:22

我在想,能不能在PyQt和Boost.Python之间共享一些小部件。

我打算在我的一个使用Qt的应用程序里嵌入一个Python解释器。我希望我的应用用户能够把他们自己的界面小部件嵌入到用C++编写的小部件里,并通过Boost.Python来使用。

这有可能吗?如果可以的话,应该怎么做呢?

1 个回答

2

我尝试为这个写一些代理代码,但还没完全成功。这是一个开始,试图解决这个问题,但 dir() 函数用不了。直接调用函数倒是能稍微工作。

我的想法是创建一个额外的 Python 对象,把它包裹在 SIP 中,如果原来的 boost.python 对象没有匹配的属性,就把任何调用或属性转发给这个新对象。

不过,我对 Python 还不是很精通,没办法让它正常工作。 :(

(我把这个变成了一个维基,大家可以在这里编辑和更新,因为这段代码只是个半成品。)

c++:

#include "stdafx.h"    
#include <QtCore/QTimer>

class MyWidget : public QTimer
{
public:
    MyWidget() {}
    void foo() { std::cout << "yar\n"; }
    unsigned long myself() { return reinterpret_cast<unsigned long>(this); }
};

#ifdef _DEBUG
BOOST_PYTHON_MODULE(PyQtBoostPythonD)
#else
BOOST_PYTHON_MODULE(PyQtBoostPython)
#endif
{
    using namespace boost::python;

    class_<MyWidget, bases<>, MyWidget*, boost::noncopyable>("MyWidget").
        def("foo", &MyWidget::foo).
        def("myself", &MyWidget::myself);
} 

Python:

from PyQt4.Qt import *
import sys

import sip
from PyQtBoostPythonD import * # the module compiled from cpp file above

a = QApplication(sys.argv)
w = QWidget()
f = MyWidget()

def _q_getattr(self, attr):
  if type(self) == type(type(MyWidget)):
    raise AttributeError
  else:
    print "get %s" % attr
    value = getattr(sip.wrapinstance(self.myself(), QObject), attr)
    print "get2 %s returned %s" % (attr, value)
    return value

MyWidget.__getattr__ = _q_getattr

def _q_dir(self):
  r = self.__dict__
  r.update(self.__class__.__dict__)
  wrap = sip.wrapinstance(self.myself(), QObject)
  r.update(wrap.__dict__)
  r.update(wrap.__class__.__dict__)
  return r

MyWidget.__dir__ = _q_dir

f.start()
f.foo()
print dir(f)

撰写回答