Написал небольшое руководство по использованию sip. Прошу оценить полезность.
Использование sip4.7 для обертки своих классов на основе QT4.3Данное руководство описывает обертку простейшего класса на основе QLabel для его дальнейшего использования в проектах Python.
При написании руководства использовались следующие продукты:
QT-4.3.1 (
www.trolltech.com)
PyQT-4.3 (
www.riverbankcomputing.co.uk)
python-2.5 (
www.python.org)
sip-4.7 (
www.riverbankcomputing.co.uk)
Все продукты OpenSource.
Примеры разрабатывались и тестировались под ОС Fedora 7.
Содержание статьи:
1. Написание класса Hello наследуемого от QLabel;
2. Написание обертки класса Hello;
3. Написание скрипта конфигурации сборки модуля python;
4. Сборка и установка модуля Hello;
5. Тестовый пример.
1. Написание класса Hello наследуемого от QLabel
Создаем заголовочный файл hello.h для класса Hello следующего вида:
#ifndef HELLO_H
#define HELLO_H
#if defined(Q_WS_WIN)
// директивы импорта/экспорта для создания dll для Windows
#if defined(HELLO_DLL)
#define HELLO_EXPORT __declspec(dllimport)
#elif defined(HELLO_MAKE_DLL)
#define HELLO_EXPORT __declspec(dllexport)
#endif
#endif
#if !defined(HELLO_EXPORT)
#define HELLO_EXPORT
#endif
#include <QLabel>
#include <QWidget>
#include <QString>
class HELLO_EXPORT Hello : public QLabel {
Q_OBJECT
public:
Hello(QWidget *parent, const char *name = 0);
};
#endif
Создаем файл hello.cpp, в котором реализация конструктора класса:
#include "hello.h"
Hello::Hello(QWidget *parent, const char *name)
: QLabel(parent)
{
setText("hello from Qt");
}
Создаем файл проекта QT:
TEMPLATE = lib # в результате компиляции необходимо получить динамическую библиотеку
HEADERS=hello.h # подключаем заголовочный файл класса Hello
SOURCES=hello.cpp # подключаем файл исходника класса Hello
Теперь компилируем библиотеку командами:
qmake
make
В результате получим библиотеку
libhello.so.1.0.0
и три ссылки на нее:
libhello.so
libhello.so.1
libhello.so.1.0
Библиотека для динамического подключения класса Hello готова.
2. Написание обертки класса Hello.
Создаем файл обертки hello.sip
%Module hello 0 // указываем наименование модуля hello и номер версии 0
// подключаем модули ядра и графического интерфейса
%Import QtCore/QtCoremod.sip
%Import QtGui/QtGuimod.sip
class Hello : QLabel {
%TypeHeaderCode
#include "hello.h" // вписываем сюда заголовочный файл класса Hello
%End
public:
Hello(QWidget * /TransferThis/, const char * = 0); //описываем конструктор класса
};
Примечание TransferThis необходимо, чтобы в дальнейшем при использовании класса, сборщик мусора Python корректно удалял объект.
3. Написание скрипта конфигурации сборки модуля python.
Создаем скрипт конфигурации configure.py:
import os
import sipconfig
from PyQt4 import pyqtconfig # импортируем модуль конфигурации Qt
build_file = "hello.sbf" # используется для сборки
config = pyqtconfig.Configuration()
qt_sip_flags = config.pyqt_sip_flags # флаги конфигурации sip для PyQt
# Run SIP to generate the code. Note that we tell SIP where to find the qt
# module's specification files using the -I flag.
# запускаем sip для генерации кода обертки, на вход файл сборки, путь к директории sip, флаги sip (из настроек PyQt), файл обертки класса hello
os.system(" ".join([config.sip_bin, "-c", ".", "-b", build_file, "-I", config.pyqt_sip_dir, qt_sip_flags, "hello.sip"]))
# переходим к созданию файла конфигурации сборки
installs = []
installs.append(["hello.sip", os.path.join(config.pyqt_sip_dir, "hello")])
installs.append(["helloconfig.py", config.pyqt_sip_dir])
# создание файла сборки Makefile модуля hello
makefile = pyqtconfig.QtGuiModuleMakefile(
configuration=config,
build_file=build_file,
installs=installs
)
# добавляем путь с библиотекой (текущая директория) и саму библиотеку к файлу сборки
# (ВНИМАНИЕ: никаких префиксов типа lib и суффиксов типа dll не указываем)
makefile.extra_lib_dirs.append(".")
makefile.extra_libs.append("hello")
# генерируем Makefile
makefile.generate()
# далее создаем конфигурационный модуль
# указываем флаги конфигурации sip
content = {
"hello_sip_dir": config.pyqt_sip_dir,
"hello_sip_flags": qt_sip_flags
}
# создаем конфигурационный модуль helloconfig.py из шаблона helloconfig.py.in
sipconfig.create_config_module("helloconfig.py", "helloconfig.py.in", content)
Шаблон создания конфигурационного модуля helloconfig.py.in (был взят из руководства по sip с
www.riverbankcomputing.co.uk):
from PyQt4 import pyqtconfig
# These are installation specific values created when Hello was configured.
# The following line will be replaced when this template is used to create
# the final configuration module.
# @SIP_CONFIGURATION@
class Configuration(pyqtconfig.Configuration):
"""The class that represents Hello configuration values.
"""
def __init__(self, sub_cfg=None):
"""Initialise an instance of the class.
sub_cfg is the list of sub-class configurations. It should be None
when called normally.
"""
# This is all standard code to be copied verbatim except for the
# name of the module containing the super-class.
if sub_cfg:
cfg = sub_cfg
else:
cfg = []
cfg.append(_pkg_config)
pyqtconfig.Configuration.__init__(self, cfg)
class HelloModuleMakefile(pyqtconfig.QtGuiModuleMakefile):
"""The Makefile class for modules that %Import hello.
"""
def finalise(self):
"""Finalise the macros.
"""
# Make sure our C++ library is linked.
self.extra_libs.append("hello")
# Let the super-class do what it needs to.
pyqtconfig.QtGuiModuleMakefile.finalise(self)
4. Сборка и установка модуля Hello.
Собираем и устанавливаем модуль следующими командами:
python configure.py
make
sudo make install
5. Тестовый пример, показывающий результат проделанной работы (файл test.py):
import hello # импортируем созданный модуль
import sys
from PyQt4 import QtGui
if __name__=="__main__":
app = QtGui.QApplication(sys.argv)
mainwindow = hello.Hello(None) # создаем объект нашего класса Hello
mainwindow.show() # показываем его экране
sys.exit(app.exec_())