diff --git a/pyste/NEWS b/pyste/NEWS index edb99984..018e02a6 100644 --- a/pyste/NEWS +++ b/pyste/NEWS @@ -1,6 +1,12 @@ 07 Apr 2003 -Removed the warnings about forward declarations: it was not accurate enough. -Another strategy must be thought of. +- Removed the warnings about forward declarations: it was not accurate enough. + Another strategy must be thought of. +- Fixed bug in the --multiple mode, where the order of the class instantiations + could end up wrong. +- Lots of fixes in the documentation, pointed out by Dirk Gerrits. Thanks Dirk! +- Fixed support for the return_opaque_pointer policy (the support macro was not + being declared). + 06 Apr 2003 Support for the improved static data members support of Boost.Python. diff --git a/pyste/doc/introduction.html b/pyste/doc/introduction.html index cb4270da..d86179e2 100644 --- a/pyste/doc/introduction.html +++ b/pyste/doc/introduction.html @@ -51,7 +51,7 @@ Here's the interface file for it, named world.pyste:

and that's it!

-The next step is invoke pyste in the command-line:

+The next step is invoke Pyste in the command-line:

python pyste.py --module=hello world.pyste

this will create a file "hello.cpp" in the directory where the command was run.

diff --git a/pyste/doc/policies.html b/pyste/doc/policies.html index da394865..3ad28a1d 100644 --- a/pyste/doc/policies.html +++ b/pyste/doc/policies.html @@ -69,7 +69,7 @@ and set the policy for it, otherwise the generated cpp won't compile. Note that, for functions/methods that return const T&, the policy return_value_policy<copy_const_reference>() wil be used by default, because that's normally what you want. You can change it to something else if you need -to, thought. +to, though. diff --git a/pyste/doc/pyste.txt b/pyste/doc/pyste.txt index 072b16b2..945b2364 100644 --- a/pyste/doc/pyste.txt +++ b/pyste/doc/pyste.txt @@ -30,7 +30,7 @@ Here's the interface file for it, named [^world.pyste]: and that's it! -The next step is invoke pyste in the command-line: +The next step is invoke Pyste in the command-line: [pre python pyste.py --module=hello world.pyste] @@ -51,17 +51,17 @@ Pyste supports the following features: [page Running Pyste] -To run pyste, you will need: +To run Pyste, you will need: -* Python 2.2, avaiable at [@http://www.python.org python's website]. +* Python 2.2, available at [@http://www.python.org python's website]. * The great [@http://effbot.org elementtree] library, from Fredrik Lundh. * The excellent GCCXML, from Brad King. -Installation for the tools is avaiable in their respective webpages. +Installation for the tools is available in their respective webpages. [blurb [$theme/note.gif] GCCXML must be accessible in the PATH environment variable, so -that pyste can call it. How to do this varies from platform to platform. +that Pyste can call it. How to do this varies from platform to platform. ] [h2 Ok, now what?] @@ -87,7 +87,7 @@ where options are: --no-using do not declare "using namespace boost"; use explicit declarations instead --pyste-ns= set the namespace where new types will be declared; - default is "pyste" + default is the empty namespace --debug writes the xml for each file parsed in the current directory -h, --help print this help and exit @@ -97,11 +97,11 @@ where options are: Options explained: -The [^-I] and [^-D] are preprocessor flags, which are needed by gccxml to parse -the header files correctly and by pyste to find the header files declared in the +The [^-I] and [^-D] are preprocessor flags, which are needed by GCCXML to parse +the header files correctly and by Pyste to find the header files declared in the interface files. -[^--multiple] tells pyste to generate multiple cpps for this module (one for +[^--multiple] tells Pyste to generate multiple cpps for this module (one for each header parsed) in the directory named by [^--out], instead of the usual single cpp file. This mode is useful during development of a binding, because you are constantly changing source files, re-generating the bindings and @@ -110,7 +110,7 @@ recompiling. This saves a lot of time in compiling. [^--out] names the output file (default: [^.cpp]), or in multiple mode, names a output directory for the files (default: [^]). -[^--no-using] tells pyste to don't declare "[^using namespace boost;]" in the +[^--no-using] tells Pyste to don't declare "[^using namespace boost;]" in the generated cpp, using the namespace boost::python explicitly in all declarations. Use only if you're having a name conflict in one of the files. @@ -118,7 +118,7 @@ Use [^--pyste-ns] to change the namespace where new types are declared (for instance, the virtual wrappers). Use only if you are having any problems. By default, Pyste uses the empty namespace. -[^--debug] will write in the current directory a xml file as outputted by gccxml +[^--debug] will write in the current directory a xml file as outputted by GCCXML for each header parsed. Useful for bug reports. [^-h, --help, -v, --version] are self-explaining, I believe. ;) @@ -160,7 +160,7 @@ Although you don't have to install [@http://psyco.sourceforge.net/ Psyco] to use The interface files are the heart of Pyste. The user creates one or more interface files declaring the classes and functions he wants to export, and then -invokes pyste passing the interface files to it. Pyste then generates a single +invokes Pyste passing the interface files to it. Pyste then generates a single cpp file with Boost.Python code, with all the classes and functions exported. Besides declaring the classes and functions, the user has a number of other @@ -265,12 +265,12 @@ and set the policy for it, otherwise the generated cpp won't compile. Note that, for functions/methods that return [^const T&], the policy [^return_value_policy()] wil be used by default, because that's normally what you want. You can change it to something else if you need -to, thought. +to, though. ] [page:1 Templates] -Template Classes can easily exported too, but you can't export the "Template" +Template classes can easily be exported too, but you can't export the template itself... 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. @@ -297,7 +297,7 @@ rename the instantiations: 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] class +Note that you can rename, exclude, set policies, etc, in the [^Template] object like you would do with a [^Function] or a [^Class]. This changes affect all [*future] instantiations: @@ -318,7 +318,7 @@ If you want to change a option of a particular instantiation, you can do so: [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 pass +When you want to instantiate a template with more than one type, you can pass either a string with the types separated by whitespace, or a list of strings '''("int double" or ["int", "double"]''' would both work). ] @@ -329,8 +329,8 @@ Suppose you have this function: std::vector names(); -But you don't want to export [^std::vector], you want this function -to return a python list of strings. Boost.Python has an excellent support for +But you don't want to export [^std::vector], you want this function +to return a python list of strings. Boost.Python has excellent support for that: list names_wrapper() @@ -338,7 +338,11 @@ that: list result; // call original function vector v = names(); - // put each string from the vector in the list + // put all the strings inside the python list + vector::iterator it; + for (it = v.begin(); it != v.end(); ++it){ + result.append(*it); + } return result; } @@ -360,13 +364,13 @@ You can optionally declare the function in the interface file itself: """ list names_wrapper() { - // call name() and convert the vector to a list... + // 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 done with methods too. Just remember that the first +The same mechanism can be used with methods too. Just remember that the first parameter of wrappers for methods is a pointer to the class, like in Boost.Python: @@ -449,7 +453,7 @@ Pyste for now has manual support for smart pointers. Suppose: } To make [^newC] and [^printC] work correctly, you have to tell Pyste that a -conversor for [^boost::shared_ptr] is needed. +convertor for [^boost::shared_ptr] is needed. C = Class('C', 'C.h') use_shared_ptr(C) @@ -458,6 +462,6 @@ conversor for [^boost::shared_ptr] is needed. For [^std::auto_ptr]'s, use the function [^use_auto_ptr]. -This system is temporary, and in the future the conversors will automatically be +This system is temporary, and in the future the converters will automatically be exported if needed, without the need to tell Pyste about them explicitly. diff --git a/pyste/doc/running_pyste.html b/pyste/doc/running_pyste.html index 95e5fb61..db02af8a 100644 --- a/pyste/doc/running_pyste.html +++ b/pyste/doc/running_pyste.html @@ -25,19 +25,19 @@

-To run pyste, you will need:

-
  • Python 2.2, avaiable at +To run Pyste, you will need:

    +

    -Installation for the tools is avaiable in their respective webpages.

    +Installation for the tools is available in their respective webpages.

    GCCXML must be accessible in the PATH environment variable, so -that pyste can call it. How to do this varies from platform to platform. +that Pyste can call it. How to do this varies from platform to platform.
    @@ -62,7 +62,7 @@ where options are: --no-using do not declare "using namespace boost"; use explicit declarations instead --pyste-ns=<name> set the namespace where new types will be declared; - default is "pyste" + default is the empty namespace --debug writes the xml for each file parsed in the current directory -h, --help print this help and exit @@ -71,11 +71,12 @@ where options are:

    Options explained:

    -The -I and -D are preprocessor flags, which are needed by gccxml to parse -the header files correctly and by pyste to find the header files declared in the +The -I and -D are preprocessor flags, which are needed by +GCCXML to parse +the header files correctly and by Pyste to find the header files declared in the interface files.

    ---multiple tells pyste to generate multiple cpps for this module (one for +--multiple tells Pyste to generate multiple cpps for this module (one for each header parsed) in the directory named by --out, instead of the usual single cpp file. This mode is useful during development of a binding, because you are constantly changing source files, re-generating the bindings and @@ -84,7 +85,7 @@ recompiling. This saves a lot of time in compiling.

    --out names the output file (default: <module>.cpp), or in multiple mode, names a output directory for the files (default: <module>).

    ---no-using tells pyste to don't declare "using namespace boost;" in the +--no-using tells Pyste to don't declare "using namespace boost;" in the generated cpp, using the namespace boost::python explicitly in all declarations. Use only if you're having a name conflict in one of the files.

    @@ -92,7 +93,8 @@ Use --pyste-ns to change the namespace where new types are declared (fo instance, the virtual wrappers). Use only if you are having any problems. By default, Pyste uses the empty namespace.

    ---debug will write in the current directory a xml file as outputted by gccxml +--debug will write in the current directory a xml file as outputted by +GCCXML for each header parsed. Useful for bug reports.

    -h, --help, -v, --version are self-explaining, I believe. ;)

    diff --git a/pyste/doc/smart_pointers.html b/pyste/doc/smart_pointers.html index 902709fe..e63b49ff 100644 --- a/pyste/doc/smart_pointers.html +++ b/pyste/doc/smart_pointers.html @@ -45,7 +45,7 @@ Pyste for now has manual support for smart pointers. Suppose:

    To make newC and printC work correctly, you have to tell Pyste that a -conversor for boost::shared_ptr<C> is needed.

    +convertor for boost::shared_ptr<C> is needed.

         C = Class('C', 'C.h')
         use_shared_ptr(C)
    @@ -55,7 +55,7 @@ conversor for boost::shared_ptr<C> is needed.

    For std::auto_ptr's, use the function use_auto_ptr.

    -This system is temporary, and in the future the conversors will automatically be +This system is temporary, and in the future the converters will automatically be exported if needed, without the need to tell Pyste about them explicitly.

    diff --git a/pyste/doc/templates.html b/pyste/doc/templates.html index 58548c72..81dfa1e9 100644 --- a/pyste/doc/templates.html +++ b/pyste/doc/templates.html @@ -25,7 +25,7 @@

    -Template Classes can easily exported too, but you can't export the "Template" +Template classes can easily be exported too, but you can't export the template itself... 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.

    @@ -55,7 +55,7 @@ rename the instantiations:

    rename(double_inst, "DPoint")

    -Note that you can rename, exclude, set policies, etc, in the Template class +Note that you can rename, exclude, set policies, etc, in the Template object like you would do with a Function or a Class. This changes affect all future instantiations:

    @@ -80,7 +80,7 @@ If you want to change a option of a particular instantiation, you can do so:

    What if my template accepts more than one type?

    -When you want to instantiate a Template with more than one type, you can pass +When you want to instantiate a template with more than one type, you can pass either a string with the types separated by whitespace, or a list of strings ("int double" or ["int", "double"] would both work). diff --git a/pyste/doc/the_interface_files.html b/pyste/doc/the_interface_files.html index 77246af7..0e78e4ec 100644 --- a/pyste/doc/the_interface_files.html +++ b/pyste/doc/the_interface_files.html @@ -27,7 +27,7 @@

    The interface files are the heart of Pyste. The user creates one or more interface files declaring the classes and functions he wants to export, and then -invokes pyste passing the interface files to it. Pyste then generates a single +invokes Pyste passing the interface files to it. Pyste then generates a single cpp file with Boost.Python code, with all the classes and functions exported.

    diff --git a/pyste/doc/wrappers.html b/pyste/doc/wrappers.html index 66ce4413..63c9a9ce 100644 --- a/pyste/doc/wrappers.html +++ b/pyste/doc/wrappers.html @@ -30,9 +30,9 @@ Suppose you have this function:

    std::vector<std::string> names();

    -But you don't want to export std::vector<string>, you want this function +But you don't want to export std::vector<std::string>, you want this function to return a python list of strings. -Boost.Python has an excellent support for +Boost.Python has excellent support for that:

         list names_wrapper()
    @@ -40,7 +40,11 @@ that:

    list result; // call original function vector<string> v = names(); - // put each string from the vector in the list + // 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; } @@ -64,14 +68,14 @@ You can optionally declare the function in the interface file itself:

    """ list names_wrapper() { - // call name() and convert the vector to a list... + // 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 done with methods too. Just remember that the first +The same mechanism can be used with methods too. Just remember that the first parameter of wrappers for methods is a pointer to the class, like in Boost.Python:

    diff --git a/pyste/example/.cvsignore b/pyste/example/.cvsignore index 38b475ff..7ee0168b 100644 --- a/pyste/example/.cvsignore +++ b/pyste/example/.cvsignore @@ -1,2 +1,2 @@ -*.cpp .sconsign +*.obj diff --git a/pyste/example/basic.cpp b/pyste/example/basic.cpp new file mode 100644 index 00000000..9e6ed996 --- /dev/null +++ b/pyste/example/basic.cpp @@ -0,0 +1,8 @@ +#include "basic.h" + +namespace basic { + + int C::static_value = 3; + const int C::const_static_value = 100; + +} diff --git a/pyste/example/basic.h b/pyste/example/basic.h index 92ff55bc..16469e95 100644 --- a/pyste/example/basic.h +++ b/pyste/example/basic.h @@ -1,3 +1,7 @@ +#ifndef BASIC_H +#define BASIC_H + + #include namespace basic { @@ -24,27 +28,26 @@ struct C const int const_value; }; -int C::static_value = 3; -const int C::const_static_value = 100; - -int call_f(C& c) +inline int call_f(C& c) { return c.f(); } -int call_f(C& c, int x) +inline int call_f(C& c, int x) { return c.f(x); } -int get_static() +inline int get_static() { return C::static_value; } -int get_value(C& c) +inline int get_value(C& c) { return c.value; } } + +#endif diff --git a/pyste/example/enums.h b/pyste/example/enums.h index 398b66c0..207001e0 100644 --- a/pyste/example/enums.h +++ b/pyste/example/enums.h @@ -1,3 +1,6 @@ +#ifndef ENUMS_H +#define ENUMS_H + namespace enums { enum color { red, blue }; @@ -17,3 +20,5 @@ struct X }; } + +#endif diff --git a/pyste/example/header_test.h b/pyste/example/header_test.h index 85cb5ee0..286f5449 100644 --- a/pyste/example/header_test.h +++ b/pyste/example/header_test.h @@ -1,3 +1,6 @@ +#ifndef HEADER_TEST_H +#define HEADER_TEST_H + #include #include @@ -5,7 +8,7 @@ namespace header_test { enum choice { red, blue }; -std::string choice_str(choice c) +inline std::string choice_str(choice c) { std::map choice_map; choice_map[red] = "red"; @@ -24,3 +27,5 @@ struct C }; } + +#endif diff --git a/pyste/example/nested.cpp b/pyste/example/nested.cpp new file mode 100644 index 00000000..9a37a226 --- /dev/null +++ b/pyste/example/nested.cpp @@ -0,0 +1,4 @@ +#include "nested.h" + +int nested::X::staticXValue = 10; +int nested::X::Y::staticYValue = 20; diff --git a/pyste/example/nested.h b/pyste/example/nested.h index c4025dd3..e62adab5 100644 --- a/pyste/example/nested.h +++ b/pyste/example/nested.h @@ -1,3 +1,6 @@ +#ifndef NESTED_H +#define NESTED_H + namespace nested { struct X @@ -16,9 +19,8 @@ struct X int valueX; }; -int X::staticXValue = 10; -int X::Y::staticYValue = 20; - typedef X Root; } + +#endif diff --git a/pyste/example/opaque.h b/pyste/example/opaque.h new file mode 100644 index 00000000..50ebf508 --- /dev/null +++ b/pyste/example/opaque.h @@ -0,0 +1,47 @@ +#ifndef OPAQUE_H +#define OPAQUE_H + +#include + +namespace opaque { + + +struct C { + C(int v): value(v) {} + int value; +}; + + +inline C* new_C() +{ + return new C(10); +} + +inline int get(C* c) +{ + return c->value; +} + +struct D { + D(double v): value(v) {} + double value; +}; + +struct A +{ + D* new_handle() + { + return new D(3.0); + } + + double get(D* d) + { + return d->value; + } + + int f(int x=0) { return x; } +}; + +} + +#endif diff --git a/pyste/example/opaque.pyste b/pyste/example/opaque.pyste new file mode 100644 index 00000000..2e6a3bc5 --- /dev/null +++ b/pyste/example/opaque.pyste @@ -0,0 +1,5 @@ +foo = Function('opaque::new_C', 'opaque.h') +set_policy(foo, return_value_policy(return_opaque_pointer)) +Function('opaque::get', 'opaque.h' ) +A = Class('opaque::A', 'opaque.h') +set_policy(A.new_handle, return_value_policy(return_opaque_pointer)) diff --git a/pyste/example/operators.cpp b/pyste/example/operators.cpp new file mode 100644 index 00000000..cc8e881d --- /dev/null +++ b/pyste/example/operators.cpp @@ -0,0 +1,3 @@ +#include "operators.h" + +double operators::C::x = 10; diff --git a/pyste/example/operators.h b/pyste/example/operators.h index 6d92c4ea..a9d3759e 100644 --- a/pyste/example/operators.h +++ b/pyste/example/operators.h @@ -1,3 +1,7 @@ +#ifndef OPERATORS_H +#define OPERATORS_H + + #include namespace operators { @@ -31,9 +35,7 @@ struct C operator const char*() { return "C"; } }; -double C::x = 10; - -const C operator*(const C& lhs, const C& rhs) +inline const C operator*(const C& lhs, const C& rhs) { C c; c.value = lhs.value * rhs.value; @@ -42,3 +44,6 @@ const C operator*(const C& lhs, const C& rhs) } + + +#endif diff --git a/pyste/example/smart_ptr.h b/pyste/example/smart_ptr.h index 2ba44972..c8847cd8 100644 --- a/pyste/example/smart_ptr.h +++ b/pyste/example/smart_ptr.h @@ -1,3 +1,7 @@ +#ifndef SMART_PTR_H +#define SMART_PTR_H + + #include #include @@ -8,7 +12,7 @@ struct C int value; }; -boost::shared_ptr NewC() { return boost::shared_ptr( new C() ); } +inline boost::shared_ptr NewC() { return boost::shared_ptr( new C() ); } struct D { @@ -18,5 +22,8 @@ private: boost::shared_ptr ptr; }; -std::auto_ptr NewD() { return std::auto_ptr( new D() ); } +inline std::auto_ptr NewD() { return std::auto_ptr( new D() ); } + } + +#endif diff --git a/pyste/example/virtual.h b/pyste/example/virtual.h index 17f70361..32ef3ebf 100644 --- a/pyste/example/virtual.h +++ b/pyste/example/virtual.h @@ -20,6 +20,6 @@ private: virtual const char* name() { return "C"; } }; -int call_f(C& c) { return c.f(); } +inline int call_f(C& c) { return c.f(); } } diff --git a/pyste/example/virtual2.h b/pyste/example/virtual2.h index c02cd2cd..0f5aab32 100644 --- a/pyste/example/virtual2.h +++ b/pyste/example/virtual2.h @@ -13,14 +13,14 @@ struct B: A virtual int f2() { return 20; } }; -int call_fs(A*a) +inline int call_fs(A*a) { int r = a->f1(); B* b = dynamic_cast(a); return r + b->f2(); } -int call_f(A* a) +inline int call_f(A* a) { return a->f(); } diff --git a/pyste/example/wrappertest.h b/pyste/example/wrappertest.h index 82887230..4cce28ee 100644 --- a/pyste/example/wrappertest.h +++ b/pyste/example/wrappertest.h @@ -6,7 +6,7 @@ namespace wrappertest { -std::vector Range(int count) +inline std::vector Range(int count) { std::vector v; v.reserve(count); @@ -40,7 +40,7 @@ struct A virtual int f() { return 1; }; }; -int call_foo(A* a){ return a->f(); } +inline int call_foo(A* a){ return a->f(); } } #endif diff --git a/pyste/example/wrappertest_wrappers.h b/pyste/example/wrappertest_wrappers.h index 46bf65ec..a0b5d946 100644 --- a/pyste/example/wrappertest_wrappers.h +++ b/pyste/example/wrappertest_wrappers.h @@ -19,10 +19,10 @@ list VectorToList(const std::vector & v) return res; } -list RangeWrapper(int count){ +inline list RangeWrapper(int count){ return VectorToList(wrappertest::Range(count)); } -int f_wrapper(wrappertest::A*) { return 10; } +inline int f_wrapper(wrappertest::A*) { return 10; } #endif diff --git a/pyste/src/ClassExporter.py b/pyste/src/ClassExporter.py index 2c615e27..a6c3df6b 100644 --- a/pyste/src/ClassExporter.py +++ b/pyste/src/ClassExporter.py @@ -2,6 +2,7 @@ import exporters from Exporter import Exporter from declarations import * from settings import * +from policies import * from SingleCodeUnit import SingleCodeUnit from EnumExporter import EnumExporter from utils import makeid, enumerate @@ -35,12 +36,14 @@ class ClassExporter(Exporter): self.sections['scope'] = [] # declarations: outside the BOOST_PYTHON_MODULE macro self.sections['declaration'] = [] + self.sections['declaration-outside'] = [] self.sections['include'] = [] # a list of Constructor instances self.constructors = [] self.wrapper_generator = None # a list of code units, generated by nested declarations self.nested_codeunits = [] + self._exported_opaque_pointers = {} def ScopeName(self): @@ -96,6 +99,7 @@ class ClassExporter(Exporter): self.ExportNestedClasses(exported_names) self.ExportNestedEnums() self.ExportSmartPointer() + self.ExportOpaquePointerPolicies() self.Write(codeunit) @@ -149,6 +153,9 @@ class ClassExporter(Exporter): declarations += nested_unit.Section('declaration') if declarations: codeunit.Write('declaration', declarations + '\n') + declarations_outside = '\n'.join(self.sections['declaration-outside']) + if declarations_outside: + codeunit.Write('declaration-outside', declarations_outside + '\n') # write the includes to the codeunit includes = '\n'.join(self.sections['include']) @@ -546,6 +553,19 @@ class ClassExporter(Exporter): smart_ptr = self.info.smart_ptr if smart_ptr: self.Add('template', smart_ptr % self.class_.FullName()) + + + def ExportOpaquePointerPolicies(self): + # check all methods for 'return_opaque_pointer' policies + methods = [x for x in self.public_members if isinstance(x, Method)] + for method in methods: + return_opaque_policy = return_value_policy(return_opaque_pointer) + if self.info[method.name].policy == return_opaque_policy: + macro = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)' % method.result.name + if macro not in self._exported_opaque_pointers: + self.Add('declaration-outside', macro) + self._exported_opaque_pointers[macro] = 1 + #============================================================================== diff --git a/pyste/src/FunctionExporter.py b/pyste/src/FunctionExporter.py index 1207dd87..fb73ce5c 100644 --- a/pyste/src/FunctionExporter.py +++ b/pyste/src/FunctionExporter.py @@ -14,6 +14,7 @@ class FunctionExporter(Exporter): def __init__(self, info, tail=None): Exporter.__init__(self, info, tail) + self._exported_opaque_pointers = {} def Export(self, codeunit, exported_names): @@ -22,7 +23,8 @@ class FunctionExporter(Exporter): self.info.policy = exporterutils.HandlePolicy(decl, self.info.policy) exporterutils.WarnForwardDeclarations(decl) self.ExportDeclaration(decl, len(decls) == 1, codeunit) - self.GenerateOverloads(decls, codeunit) + self.ExportOpaquePointer(decl, codeunit) + self.GenerateOverloads(decls, codeunit) def ExportDeclaration(self, decl, unique, codeunit): @@ -75,6 +77,15 @@ class FunctionExporter(Exporter): return '' + def ExportOpaquePointer(self, function, codeunit): + if self.info.policy == return_value_policy(return_opaque_pointer): + type = function.result.name + macro = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)' % type + if macro not in self._exported_opaque_pointers: + codeunit.Write('declaration-outside', macro) + self._exported_opaque_pointers[macro] = 1 + + def Order(self): return self.info.name diff --git a/pyste/src/HeaderExporter.py b/pyste/src/HeaderExporter.py index 2ff7876b..de63b1b0 100644 --- a/pyste/src/HeaderExporter.py +++ b/pyste/src/HeaderExporter.py @@ -65,7 +65,7 @@ class HeaderExporter(Exporter): def Unit(self): - return self.info.include + return None # doesn't write anything by himself def Order(self): diff --git a/pyste/src/MultipleCodeUnit.py b/pyste/src/MultipleCodeUnit.py index b98071e6..ca4528b9 100644 --- a/pyste/src/MultipleCodeUnit.py +++ b/pyste/src/MultipleCodeUnit.py @@ -34,7 +34,10 @@ class MultipleCodeUnit(object): def SetCurrent(self, code_unit_name): 'Changes the current code unit' try: - codeunit = self.codeunits[code_unit_name] + if code_unit_name is not None: + codeunit = self.codeunits[code_unit_name] + else: + codeunit = None except KeyError: filename = self._FileName(code_unit_name) function_name = self._FunctionName(code_unit_name) @@ -52,19 +55,14 @@ class MultipleCodeUnit(object): current = property(Current, SetCurrent) - def _CheckCurrent(self): - if self.current is None: - raise RuntimeError, "No current code unit to write to!" - - def Write(self, section, code): - self._CheckCurrent() - self.current.Write(section, code) + if self._current is not None: + self.current.Write(section, code) def Section(self, section): - self._CheckCurrent() - return self.current.Section(section) + if self._current is not None: + return self.current.Section(section) def _CreateOutputDir(self): diff --git a/pyste/src/SingleCodeUnit.py b/pyste/src/SingleCodeUnit.py index 67e970d5..1ac590f9 100644 --- a/pyste/src/SingleCodeUnit.py +++ b/pyste/src/SingleCodeUnit.py @@ -22,8 +22,13 @@ class SingleCodeUnit: self.filename = filename # define the avaiable sections self.code = {} + # include section self.code['include'] = '' + # declaration section (inside namespace) self.code['declaration'] = '' + # declaration (outside namespace) + self.code['declaration-outside'] = '' + # inside BOOST_PYTHON_MACRO self.code['module'] = '' # create the default module definition self.module_definition = 'BOOST_PYTHON_MODULE(%s)' % modulename @@ -37,7 +42,7 @@ class SingleCodeUnit: def Merge(self, other): - for section in ('include', 'declaration', 'module'): + for section in ('include', 'declaration', 'declaration-outside', 'module'): self.code[section] = self.code[section] + other.code[section] @@ -60,21 +65,20 @@ class SingleCodeUnit: fout.write(left_equals('Using')) fout.write('using namespace boost::python;\n\n') # declarations - if self.code['declaration']: - pyste_namespace = namespaces.pyste[:-2] + declaration = self.code['declaration'] + declaration_outside = self.code['declaration-outside'] + if declaration_outside or declaration: fout.write(left_equals('Declarations')) - fout.write('namespace %s {\n\n\n' % pyste_namespace) - fout.write(self.code['declaration']) - fout.write('\n\n}// namespace %s\n' % pyste_namespace) - fout.write(space) + fout.write(declaration_outside + '\n\n') + if declaration: + pyste_namespace = namespaces.pyste[:-2] + fout.write('namespace %s {\n\n\n' % pyste_namespace) + fout.write(declaration) + fout.write('\n\n}// namespace %s\n' % pyste_namespace) + fout.write(space) # module fout.write(left_equals('Module')) fout.write(self.module_definition + '\n') fout.write('{\n') fout.write(self.code['module']) fout.write('}\n') - - - def _leftEquals(self, s): - s = '// %s ' % s - return s + ('='*(80-len(s))) + '\n' diff --git a/pyste/src/policies.py b/pyste/src/policies.py index ebb1886e..a63b5e73 100644 --- a/pyste/src/policies.py +++ b/pyste/src/policies.py @@ -19,6 +19,13 @@ class Policy: return ' >' + def __eq__(self, other): + try: + return self.Code() == other.Code() + except AttributeError: + return False + + class return_internal_reference(Policy): 'Ties the return value to one of the parameters.' diff --git a/pyste/src/pyste.py b/pyste/src/pyste.py index 26d59a9a..91f48142 100644 --- a/pyste/src/pyste.py +++ b/pyste/src/pyste.py @@ -14,7 +14,7 @@ where options are: --no-using do not declare "using namespace boost"; use explicit declarations instead --pyste-ns= set the namespace where new types will be declared; - default is "pyste" + default is the empty namespace --debug writes the xml for each file parsed in the current directory -h, --help print this help and exit @@ -34,7 +34,7 @@ from policies import * from CppParser import CppParser, CppParserError import time -__VERSION__ = '0.7.1' +__VERSION__ = '0.7.2' def RecursiveIncludes(include): 'Return a list containg the include dir and all its subdirectories' diff --git a/pyste/tests/.cvsignore b/pyste/tests/.cvsignore index 524ee449..6e8f4170 100644 --- a/pyste/tests/.cvsignore +++ b/pyste/tests/.cvsignore @@ -1,4 +1,8 @@ *.pyc +*.exp +*.lib +*.obj +*.arg *.dll *.cpp .sconsign diff --git a/pyste/tests/SConstruct b/pyste/tests/SConstruct index 54eaaf0b..e0e6070e 100644 --- a/pyste/tests/SConstruct +++ b/pyste/tests/SConstruct @@ -47,8 +47,13 @@ env = Environment( modules = [os.path.splitext(os.path.basename(x))[0] for x in glob.glob('../example/*.pyste')] for module in modules: multiple = ARGUMENTS.get('multiple', '') - if multiple: - env.SharedLibrary(target=module, source=glob.glob(module+'/*.cpp')) + example_cpp = '../example/%s.cpp' % module + if os.path.isfile(example_cpp): + sources = [example_cpp] else: - env.SharedLibrary(target=module, source=module + '.cpp') + sources = [] + if multiple: + env.SharedLibrary(target=module, source=sources + glob.glob('_%s/*.cpp'%module)) + else: + env.SharedLibrary(target=module, source=sources + ['_%s.cpp' % module]) diff --git a/pyste/tests/example_opaqueUT.py b/pyste/tests/example_opaqueUT.py new file mode 100644 index 00000000..a16dad52 --- /dev/null +++ b/pyste/tests/example_opaqueUT.py @@ -0,0 +1,18 @@ +import unittest +from opaque import * + +class OpaqueTest(unittest.TestCase): + + def testIt(self): + + c = new_C() + self.assertEqual(get(c), 10) + a = A() + d = a.new_handle() + self.assertEqual(a.get(d), 3.0) + self.assertEqual(a.f(), 0) + self.assertEqual(a.f(3), 3) + + +if __name__ == '__main__': + unittest.main() diff --git a/pyste/tests/nt_build_all.bat b/pyste/tests/nt_build_all.bat index 4788f5c4..e93eafc7 100644 --- a/pyste/tests/nt_build_all.bat +++ b/pyste/tests/nt_build_all.bat @@ -11,3 +11,4 @@ call nt_build_pyste.bat unions %1 call nt_build_pyste.bat virtual %1 call nt_build_pyste.bat virtual2 %1 call nt_build_pyste.bat wrappertest %1 +call nt_build_pyste.bat opaque %1 diff --git a/pyste/tests/nt_build_pyste.bat b/pyste/tests/nt_build_pyste.bat index 61b250d0..33023650 100644 --- a/pyste/tests/nt_build_pyste.bat +++ b/pyste/tests/nt_build_pyste.bat @@ -1,7 +1,7 @@ @echo off set BOOST_INCLUDE=D:\Programming\Libraries\boost-cvs\boost -set out=%1.cpp -if "%2" == "--multiple" set out=%1 +set out=_%1.cpp +if "%2" == "--multiple" set out=_%1 rem python ../src/pyste.py %2 -I%BOOST_INCLUDE -I../example --module=%1 --out=%out ../example/%1.pyste pyste %2 -I%BOOST_INCLUDE -I../example --module=%1 --out=%out ../example/%1.pyste diff --git a/pyste/tests/nt_clean.bat b/pyste/tests/nt_clean.bat index 1ac9dbe3..ebc04f15 100644 --- a/pyste/tests/nt_clean.bat +++ b/pyste/tests/nt_clean.bat @@ -1,16 +1,17 @@ @echo off -rm -Rf basic -rm -Rf enums -rm -Rf header_test -rm -Rf nested -rm -Rf operators -rm -Rf smart_ptr -rm -Rf templates -rm -Rf unions -rm -Rf virtual -rm -Rf virtual2 -rm -Rf wrappertest +rm -Rf _basic +rm -Rf _enums +rm -Rf _header_test +rm -Rf _nested +rm -Rf _operators +rm -Rf _smart_ptr +rm -Rf _templates +rm -Rf _unions +rm -Rf _virtual +rm -Rf _virtual2 +rm -Rf _wrappertest +rm -Rf _opaque rm -f *.cpp rm -f *.obj @@ -19,3 +20,4 @@ rm -f *.arg rm -f *.dll rm -f *.pyc rm -f *.lib +rm -f ../example/*.obj