pyste.txt

来自「Boost provides free peer-reviewed portab」· 文本 代码 · 共 665 行 · 第 1/2 页

TXT
665
字号
Even thought Pyste can identify various elements in the C++ code, like virtualmember functions, attributes, and so on, one thing that it can't do is toguess the semantics of functions that return pointers or references. In thiscase, the user must manually specify the policy. Policies are explained in the[@../../doc/tutorial/doc/call_policies.html tutorial].The policies in Pyste are named exactly as in Boost.Python, only the syntax isslightly different. For instance, this policy:    return_internal_reference<1, with_custodian_and_ward<1, 2> >()becomes in Pyste:        return_internal_reference(1, with_custodian_and_ward(1, 2))The user can specify policies for functions and virtual member functions withthe [^set_policy] function:    set_policy(f, return_internal_reference())    set_policy(C.foo, return_value_policy(manage_new_object))[blurb [$theme/note.gif] [*What if a function or member function needs a policy andthe user doesn't set one?][br][br] If a function needs a policy and onewas not set, Pyste will issue a error.  The user should then go in theinterface file and set the policy for it, otherwise the generated cpp won'tcompile.][blurb[$theme/note.gif] Note that for functions that return [^const T&], the policy[^return_value_policy<copy_const_reference>()] wil be used by default, becausethat's normally what you want. You can change it to something else if you needto, though.][page:1 Templates]Template classes can easily be exported too, but you can't export the templateitself... you have to export instantiations of it! So, if you want to export a[^std::vector], you will have to export vectors of int, doubles, etc.Suppose we have this code:    template <class T>    struct Point    {        T x;        T y;    };And we want to export [^Point]s of int and double:    Point = Template("Point", "point.h")    Point("int")    Point("double")Pyste will assign default names for each instantiation. In this example, thosewould be "[^Point_int]" and "[^Point_double]", but most of the time users will want torename the instantiations:    Point("int", "IPoint")         // renames the instantiation    double_inst = Point("double")  // another way to do the same    rename(double_inst, "DPoint")Note that you can rename, exclude, set policies, etc, in the [^Template] objectlike you would do with a [^Function] or a [^Class]. This changes affect all[*future] instantiations:    Point = Template("Point", "point.h")    Point("float", "FPoint")        // will have x and y as data members    rename(Point.x, "X")    rename(Point.y, "Y")    Point("int", "IPoint")          // will have X and Y as data members    Point("double", "DPoint")       // also will have X and Y as data memberIf you want to change a option of a particular instantiation, you can do so:    Point = Template("Point", "point.h")    Point("int", "IPoint")              d_inst = Point("double", "DPoint")           rename(d_inst.x, "X")           // only DPoint is affect by this renames,    rename(d_inst.y, "Y")           // IPoint stays intact[blurb [$theme/note.gif] [*What if my template accepts more than one type?][br][br]When you want to instantiate a template with more than one type, you can passeither a string with the types separated by whitespace, or a list of strings'''("int double" or ["int", "double"]''' would both work).][page:1 Wrappers]Suppose you have this function:    std::vector<std::string> names();But you don't want to [@../../doc/v2/faq.html#question2 to export std::vector<std::string>], you want this function to return a python list of strings. Boost.Python hasexcellent support for things like that:    list names_wrapper()    {        list result;        // call original function        vector<string> v = names();        // put all the strings inside the python list        vector<string>::iterator it;        for (it = v.begin(); it != v.end(); ++it){            result.append(*it);            }        return result;    }        BOOST_PYTHON_MODULE(test)    {        def("names", &names_wrapper);    }Nice heh? Pyste supports this mechanism too. You declare the [^names_wrapper]function in a header named "[^test_wrappers.h]" and in the interface file:    Include("test_wrappers.h")    names = Function("names", "test.h")    set_wrapper(names, "names_wrapper")You can optionally declare the function in the interface file itself:    names_wrapper = Wrapper("names_wrapper",    """    list names_wrapper()    {        // code to call name() and convert the vector to a list...    }    """)    names = Function("names", "test.h")    set_wrapper(names, names_wrapper)The same mechanism can be used with member functions too. Just remember thatthe first parameter of wrappers for member functions is a pointer to theclass, as in:    struct C    {        std::vector<std::string> names();    }    list names_wrapper(C* c)    {        // same as before, calling c->names() and converting result to a list     }And then in the interface file:    C = Class("C", "test.h")    set_wrapper(C.names, "names_wrapper")[blurb [$theme/note.gif]Even though Boost.Python accepts either a pointer or areference to the class in wrappers for member functions as the first parameter,Pyste expects them to be a [*pointer]. Doing otherwise will prevent yourcode to compile when you set a wrapper for a virtual member function.][page:1 Exporting An Entire Header]Pyste also supports a mechanism to export all declarations found in a headerfile. Suppose again our file, [^hello.h]:    struct World    {        World(std::string msg): msg(msg) {}         void set(std::string msg) { this->msg = msg; }        std::string greet() { return msg; }        std::string msg;    };    enum choice { red, blue };        void show(choice c) { std::cout << "value: " << (int)c << std::endl; } You can just use the [^AllFromHeader] construct:    hello = AllFromHeader("hello.h")this will export all the declarations found in [^hello.h], which is equivalentto write:    Class("World", "hello.h")    Enum("choice", "hello.h")    Function("show", "hello.h")Note that you can still use the functions [^rename], [^set_policy], [^exclude], etc. Just accessthe members of the header object like this:    rename(hello.World.greet, "Greet")    exclude(hello.World.set, "Set")[blurb    [$theme/note.gif] [*AllFromHeader is broken] in some cases. Until it is fixed,use at you own risk.][page:1 Smart Pointers]Pyste for now has manual support for smart pointers. Suppose:    struct C    {        int value;    };    boost::shared_ptr<C> newC(int value)    {        boost::shared_ptr<C> c( new C() );        c->value = value;        return c;    }    void printC(boost::shared_ptr<C> c)    {        std::cout << c->value << std::endl;    }To make [^newC] and [^printC] work correctly, you have to tell Pyste that aconvertor for [^boost::shared_ptr<C>] is needed.    C = Class('C', 'C.h')    use_shared_ptr(C)    Function('newC', 'C.h')    Function('printC', 'C.h')For [^std::auto_ptr]'s, use the function [^use_auto_ptr].This system is temporary, and in the future the converters will automatically beexported if needed, without the need to tell Pyste about them explicitly.[h2 Holders]If only the converter for the smart pointers is not enough and you need tospecify the smart pointer as the holder for a class, use the functions[^hold_with_shared_ptr] and [^hold_with_auto_ptr]:    C = Class('C', 'C.h')    hold_with_shared_ptr(C)    Function('newC', 'C.h')    Function('printC', 'C.h') [page:1 Global Variables]To export global variables, use the [^Var] construct:    Var("myglobal", "foo.h")Beware of non-const global variables: changes in Python won't reflect in C++!If you really must change them in Python, you will have to write some accessorfunctions, and export those.[page:1 Adding New Methods]Suppose that you want to add a function to a class, turning it into a memberfunction:    struct World    {        void set(std::string msg) { this->msg = msg; }        std::string msg;    };    std::string greet(World& w)    {        return w.msg;    }Here, we want to make [^greet] work as a member function of the class [^World]. We dothat using the [^add_method] construct:    W = Class("World", "hello.h")    add_method(W, "greet")Notice also that then you can rename it, set its policy, just like a regularmember function:    rename(W.greet, 'Greet')Now from Python:    >>> import hello    >>> w = hello.World()    >>> w.set('Ni')    >>> w.greet()    'Ni'    >>> print 'Oh no! The knights who say Ni!'    Oh no! The knights who say Ni![page:1 Inserting Code]You can insert arbitrary code in the generated cpps, just use the functions[^declaration_code] and [^module_code]. This will insert the given string in therespective sections. Example:    # file A.pyste    Class("A", "A.h")    declaration_code("/* declaration_code() comes here */\n")    module_code("/* module_code() comes here */\n")Will generate:    // Includes ====================================================================    #include <boost/python.hpp>    // Using =======================================================================    using namespace boost::python;    // Declarations ================================================================    /* declaration_code() comes here */    // Module ======================================================================    BOOST_PYTHON_MODULE(A)    {        class_< A >("A", init<  >())            .def(init< const A& >())        ;    /* module_code() comes here */    }

⌨️ 快捷键说明

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