⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sipref.txt

📁 这是关于RFC3261实现sip的源代码
💻 TXT
📖 第 1 页 / 共 5 页
字号:
    // Define the SIP wrapper to the word library.    %Module word 0    class Word {    %TypeHeaderCode    #include <word.h>    %End    public:        Word(const char *w);        char *reverse() const;    };Obviously a SIP specification file looks very much like a C++ (or C) headerfile, but SIP does not include a full C++ parser.  Let's look at thedifferences between the two files.    - The `%Module`_ directive has been added [#]_.  This is used to name the      Python module that is being created and to give it a *generation* number.      In this example these are ``word`` and ``0`` respectively.  The      generation number is effectively the version number of the module.    - The `%TypeHeaderCode`_ directive has been added.  The text between this      and the following `%End`_ directive is included literally in the code      that SIP generates.  Normally it is used, as in this case, to      ``#include`` the corresponding C++ (or C) header file [#]_.    - The declaration of the private variable ``this_word`` has been removed.      SIP does not support access to either private or protected instance      variables.If we want to we can now generate the C++ code in the current directory byrunning the following command::    sip -c . word.sipHowever, that still leaves us with the task of compiling the generated code andlinking it against all the necessary libraries.  It's much easier to use theSIP build system to do the whole thing.Using the SIP build system is simply a matter of writing a small Python script.In this simple example we will assume that the ``word`` library we are wrappingand it's header file are installed in standard system locations and will befound by the compiler and linker without having to specify any additionalflags.  In a more realistic example your Python script may take command lineoptions, or search a set of directories to deal with different configurationsand installations.This is the simplest script (conventionally called ``configure.py``)::    import os    import sipconfig    # The name of the SIP build file generated by SIP and used by the build    # system.    build_file = "word.sbf"    # Get the SIP configuration information.    config = sipconfig.Configuration()    # Run SIP to generate the code.    os.system(" ".join([config.sip_bin, "-c", ".", "-b", build_file, "word.sip"]))        # Create the Makefile.    makefile = sipconfig.SIPModuleMakefile(config, build_file)    # Add the library we are wrapping.  The name doesn't include any platform    # specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the    # ".dll" extension on Windows).    makefile.extra_libs = ["word"]    # Generate the Makefile itself.    makefile.generate()Hopefully this script is self-documenting.  The key parts are the``Configuration`` and ``SIPModuleMakefile`` classes.  The build system containsother Makefile classes, for example to build programs or to call otherMakefiles in sub-directories.After running the script (using the Python interpreter the extension module isbeing created for) the generated C++ code and ``Makefile`` will be in thecurrent directory.To compile and install the extension module, just run the followingcommands [#]_::    make    make installThat's all there is to it.See `Building Your Extension with distutils`_ for an example of how to buildthis example using distutils... [#] All SIP directives start with a ``%`` as the first non-whitespace       character of a line... [#] SIP includes many code directives like this.  They differ in where the       supplied code is placed by SIP in the generated code... [#] On Windows you might run ``nmake`` or ``mingw32-make`` instead.A Simple C Example------------------Let's now look at a very similar example of wrapping a fictional C library::    /* Define the interface to the word library. */    struct Word {        const char *the_word;    };    struct Word *create_word(const char *w);    char *reverse(struct Word *word);The corresponding SIP specification file would then look something like this::    /* Define the SIP wrapper to the word library. */    %CModule word 0    struct Word {    %TypeHeaderCode    #include <word.h>    %End        const char *the_word;    };    struct Word *create_word(const char *w) /Factory/;    char *reverse(struct Word *word);Again, let's look at the differences between the two files.    - The `%CModule`_ directive has been added.  This has the same syntax as      the `%Module`_ directive used in the previous example but tells SIP that      the library being wrapped is implemented in C rather than C++.    - The `%TypeHeaderCode`_ directive has been added.    - The Factory_ annotation has been added to the ``create_word()`` function.      This tells SIP that a newly created structure is being returned and it is      owned by Python.The ``configure.py`` build system script described in the previous example canbe used for this example without change.A More Complex C++ Example--------------------------In this last example we will wrap a fictional C++ library that contains a classthat is derived from a Qt class.  This will demonstrate how SIP allows a classhierarchy to be split across multiple Python extension modules, and willintroduce SIP's versioning system.The library contains a single C++ class called ``Hello`` which is derived fromQt's ``QLabel`` class.  It behaves just like ``QLabel`` except that the textin the label is hard coded to be ``Hello World``.  To make the example moreinteresting we'll also say that the library only supports Qt v3.0 and later,and also includes a function called ``setDefault()`` that is not implementedin the Windows version of the library.The ``hello.h`` header file looks something like this::    // Define the interface to the hello library.    #include <qlabel.h>    #include <qwidget.h>    #include <qstring.h>    class Hello : public QLabel {        // This is needed by the Qt Meta-Object Compiler.        Q_OBJECT    public:        Hello(QWidget *parent, const char *name = 0, WFlags f = 0);    private:        // Prevent instances from being copied.        Hello(const Hello &);        Hello &operator=(const Hello &);    };    #if !defined(Q_OS_WIN)    void setDefault(const QString &def);    #endifThe corresponding SIP specification file would then look something like this::    // Define the SIP wrapper to the hello library.    %Module hello 0    %Import qt/qtmod.sip    %If (Qt_3_0_0 -)    class Hello : QLabel {    %TypeHeaderCode    #include <hello.h>    %End    public:        Hello(QWidget *parent /TransferThis/, const char *name = 0, WFlags f = 0);    private:        Hello(const Hello &);    };    %If (!WS_WIN)    void setDefault(const QString &def);    %End    %EndAgain we look at the differences, but we'll skip those that we've looked at inprevious examples.    - The `%Import`_ directive has been added to specify that we are extending      the class hierarchy defined in the file ``qt/qtmod.sip``.  This file is      part of PyQt.  The build system will take care of finding the file's      exact location.    - The `%If`_ directive has been added to specify that      everything [#]_ up to the matching `%End`_ directive only applies to Qt      v3.0 and later.  ``Qt_3_0_0`` is a *tag* defined in ``qtmod.sip`` [#]_      using the `%Timeline`_ directive.  `%Timeline`_ is used to define a tag      for each version of a library's API you are wrapping allowing you to      maintain all the different versions in a single SIP specification.  The      build system provides support to ``configure.py`` scripts for working out      the correct tags to use according to which version of the library is      actually installed.    - The ``public`` keyword used in defining the super-classes has been      removed.  This is not supported by SIP.    - The TransferThis_ annotation has been added to the first argument      of the constructor.  It specifies that if the argument is not 0 (i.e. the      ``Hello`` instance being constructed has a parent) then ownership of the      instance is transferred from Python to C++.  It is needed because Qt      maintains objects (i.e. instances derived from the ``QObject`` class) in      a hierachy.  When an object is destroyed all of its children are also      automatically destroyed.  It is important, therefore, that the Python      garbage collector doesn't also try and destroy them.  This is covered in      more detail in `Ownership of Objects`_.  SIP provides many other      annotations that can be applied to arguments, functions and classes.      Multiple annotations are separated by commas.  Annotations may have      values.    - The ``=`` operator has been removed.  This operator is not supported by      SIP.    - The `%If`_ directive has been added to specify that everything up to the      matching `%End`_ directive does not apply to Windows.  ``WS_WIN`` is      another tag defined by PyQt, this time using the `%Platforms`_ directive.      Tags defined by the `%Platforms`_ directive are mutually exclusive, i.e.      only one may be valid at a time [#]_.One question you might have at this point is why bother to define the privatecopy constructor when it can never be called from Python?  The answer is toprevent the automatic generation of a public copy constructor.We now look at the ``configure.py`` script.  This is a little different to thescript in the previous examples for two related reasons.Firstly, PyQt includes a pure Python module called ``pyqtconfig`` that extendsthe SIP build system for modules, like our example, that build on top of PyQt.It deals with the details of which version of Qt is being used (i.e. itdetermines what the correct tags are) and where it is installed.  This iscalled a module's configuration module.Secondly, we generate a configuration module (called ``helloconfig``) for ourown ``hello`` module.  There is no need to do this, but if there is a chancethat somebody else might want to extend your C++ library then it would makelife easier for them.Now we have two scripts.  First the ``configure.py`` script::    import os    import sipconfig    import pyqtconfig    # The name of the SIP build file generated by SIP and used by the build    # system.    build_file = "hello.sbf"    # Get the PyQt configuration information.    config = pyqtconfig.Configuration()    # Get the extra SIP flags needed by the imported qt module.  Note that    # this normally only includes those flags (-x and -t) that relate to SIP's    # versioning system.    qt_sip_flags = config.pyqt_qt_sip_flags    # Run SIP to generate the code.  Note that we tell SIP where to find the qt    # module's specification files using the -I flag.    os.system(" ".join([config.sip_bin, "-c", ".", "-b", build_file, "-I", config.pyqt_sip_dir, qt_sip_flags, "hello.sip"]))    # We are going to install the SIP specification file for this module and    # its configuration module.    installs = []    installs.append(["hello.sip", os.path.join(config.default_sip_dir, "hello")])    installs.append(["helloconfig.py", config.default_mod_dir])    # Create the Makefile.  The QtModuleMakefile class provided by the    # pyqtconfig module takes care of all the extra preprocessor, compiler and    # linker flags needed by the Qt library.    makefile = pyqtconfig.QtModuleMakefile(        configuration=config,        build_file=build_file,        installs=installs    )    # Add the library we are wrapping.  The name doesn't include any platform    # specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the    # ".dll" extension on Windows).    makefile.extra_libs = ["hello"]    # Generate the Makefile itself.    makefile.generate()    # Now we create the configuration module.  This is done by merging a Python    # dictionary (whose values are normally determined dynamically) with a    # (static) template.    content = {        # Publish where the SIP specifications for this module will be        # installed.        "hello_sip_dir":    config.default_sip_dir,        # Publish the set of SIP flags needed by this module.  As these are the        # same flags needed by the qt module we could leave it out, but this        # allows us to change the flags at a later date without breaking        # scripts that import the configuration module.        "hello_sip_flags":  qt_sip_flags    }    # This creates the helloconfig.py module from the helloconfig.py.in    # template and the dictionary.    sipconfig.create_config_module("helloconfig.py", "helloconfig.py.in", content)Next we have the ``helloconfig.py.in`` template script::    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.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -