2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-20 16:52:15 +00:00

Compare commits

..

100 Commits

Author SHA1 Message Date
nobody
59e42fe22f This commit was manufactured by cvs2svn to create tag
'version_0-9-16'.

[SVN r19671]
2003-08-17 21:11:08 +00:00
Bruno da Silva de Oliveira
dc7ae9ed20 - removed "header_code", since we already have Include().
[SVN r19670]
2003-08-17 21:11:07 +00:00
Bruno da Silva de Oliveira
929badf4c6 Added support for insertion of user code in the generated code
[SVN r19664]
2003-08-17 19:35:00 +00:00
Bruno da Silva de Oliveira
c4a3f2c04f no message
[SVN r19652]
2003-08-16 21:11:50 +00:00
Bruno da Silva de Oliveira
a933e458b3 - Fixed a bug in the pure virtual functions
[SVN r19648]
2003-08-16 19:13:45 +00:00
Bruno da Silva de Oliveira
06b8320815 - Added exception specifiers (patch by Gottfried).
[SVN r19645]
2003-08-16 18:21:44 +00:00
Dave Abrahams
7f3aceafd2 Fix public/private error.
[SVN r19636]
2003-08-16 13:56:52 +00:00
Dave Abrahams
da5979931c class.hpp, object/select_holder.hpp, object/pointer_holder.hpp -
fix a problem which was causing value_holder<T> to be instantiated
   on abstract classes.  Now we compute the held_type at an outer
   level thereby avoiding the inner instantiation.

object_core.hpp -

   workarounds for GCC 2.x bugs

suite/indexing/detail/indexing_suite_detail.hpp -

   workaround for a CWPro8 bug


[SVN r19635]
2003-08-16 13:48:34 +00:00
Dave Abrahams
d8c7e75095 Fix the fix... again!
[SVN r19617]
2003-08-15 03:45:34 +00:00
Joel de Guzman
187506c97f added map value type (std::pair) wrapper to map_indexing_suite.hpp
[SVN r19616]
2003-08-15 03:03:27 +00:00
Joel de Guzman
145c6d1e4f moved map value type (std::pair) wrapper to map_indexing_suite.hpp
[SVN r19615]
2003-08-15 03:01:32 +00:00
Dave Abrahams
e2973f27f9 Fix the fix ;-)
[SVN r19613]
2003-08-14 22:53:30 +00:00
Dave Abrahams
976b8180ae Workaround a VC7 bug with nested enums
[SVN r19611]
2003-08-14 22:48:01 +00:00
Joel de Guzman
37acf41d43 Added map_indexing_suite test
[SVN r19600]
2003-08-14 15:05:02 +00:00
Joel de Guzman
6f26778491 Initial commit map_indexing_suite tests
[SVN r19599]
2003-08-14 15:04:25 +00:00
Joel de Guzman
834d815c87 mapping suite update
[SVN r19598]
2003-08-14 15:03:14 +00:00
Joel de Guzman
57e58c445b Tweaks to accomodate map_indexing_suite
[SVN r19588]
2003-08-14 12:14:25 +00:00
Joel de Guzman
8a1a8342d6 Initial commit map_indexing_suite
[SVN r19587]
2003-08-14 12:13:15 +00:00
Joel de Guzman
fa70ddc2c5 Preparing for std::map suite
[SVN r19566]
2003-08-12 21:21:47 +00:00
Joel de Guzman
8ca32bb494 Minor tweak in preparation for map_indexing_suite.hpp
[SVN r19565]
2003-08-12 18:36:55 +00:00
Joel de Guzman
f6c82eba0c changed def_arg to def_visitor
[SVN r19564]
2003-08-12 18:35:00 +00:00
Joel de Guzman
344044a315 updated the include path to vector_indexing_suite.hpp
[SVN r19563]
2003-08-12 18:13:19 +00:00
Joel de Guzman
b10805dc4c moved to new "suite" directory
[SVN r19562]
2003-08-12 18:09:21 +00:00
Joel de Guzman
07f397e2ed Moved to new "suite" directory
[SVN r19561]
2003-08-12 18:07:11 +00:00
Dave Abrahams
054dc439d2 Workaround msvc bug
[SVN r19553]
2003-08-12 14:17:52 +00:00
Dave Abrahams
5008dcbdd4 Make sure the class object and cast relationships are registered for
virtual function dispatch classes.


[SVN r19543]
2003-08-12 04:36:42 +00:00
Dave Abrahams
9c6650963f Use def_visitor to simplify class def(...) handling.
Workarounds for intel6 and vc6.


[SVN r19533]
2003-08-11 14:56:30 +00:00
Dave Abrahams
d482d57689 added properties tests
[SVN r19532]
2003-08-11 14:30:04 +00:00
Dave Abrahams
edf6516085 Python 2.3 compatibility.
[SVN r19530]
2003-08-11 11:07:28 +00:00
Dave Abrahams
957ac66e14 Added missing #include
Use BOOST_EXPLICIT_TEMPLATE_TYPE


[SVN r19529]
2003-08-11 02:21:34 +00:00
Dave Abrahams
07ce84c4e7 Repair bugs introduced during previous workaround
[SVN r19526]
2003-08-11 02:01:15 +00:00
Bruno da Silva de Oliveira
918636ff03 - Fixed a bug where in some classes the virtual methods were being definied incorrectly
[SVN r19525]
2003-08-10 23:21:25 +00:00
Dave Abrahams
83a6adbfa9 Added properties news item
changed the name of the static property class to
Boost.Python.StaticProperty (was Boost.Python.Class).


[SVN r19521]
2003-08-10 22:56:58 +00:00
Dave Abrahams
fcbc1d562f Added properties unit test from Roman Yakovenko
<romany-at-actimize.com>.


[SVN r19520]
2003-08-10 22:51:51 +00:00
Dave Abrahams
c3b4b58075 Extended CWPro8 overload ambiguity workaround to cover make_setter as
well as make_getter.


[SVN r19519]
2003-08-10 22:50:38 +00:00
Bruno da Silva de Oliveira
568b62a8a4 - Little bug where the memory cache was not being used
[SVN r19517]
2003-08-10 21:51:28 +00:00
Bruno da Silva de Oliveira
da34e7f507 - Abstract methods fix
- converts \ to / on windows


[SVN r19516]
2003-08-10 21:47:50 +00:00
Joel de Guzman
a0c31b47e5 refactored code + cleanup
[SVN r19508]
2003-08-10 15:20:10 +00:00
Joel de Guzman
5fb677c0c5 initial commit of container utils
[SVN r19507]
2003-08-10 15:19:23 +00:00
Bruno da Silva de Oliveira
168476382a - incremental code and some fixes
[SVN r19499]
2003-08-09 21:18:12 +00:00
Bruno da Silva de Oliveira
7fa6a29814 no message
[SVN r19498]
2003-08-09 20:57:04 +00:00
Bruno da Silva de Oliveira
f2b51da0ab - Fix a bug where a declaration was appearing more than once in an intermediate class in an hierarchy not fully-exported
[SVN r19489]
2003-08-08 02:56:04 +00:00
Joel de Guzman
53726746b8 Clean-up, refactored and added NoSlice option.
[SVN r19488]
2003-08-07 17:16:07 +00:00
Joel de Guzman
fe0b59f559 some trivial fixes.
[SVN r19485]
2003-08-07 12:29:54 +00:00
Joel de Guzman
c014dee6dc Fixed no proxy handling for containers of primitive types.
[SVN r19484]
2003-08-07 08:45:57 +00:00
Joel de Guzman
90c69d961e Added named visitor .def facility.
[SVN r19483]
2003-08-07 03:07:20 +00:00
Dave Abrahams
342f7db678 Workaround vc7.1 typeid problem with cv-qualified arrays.
[SVN r19474]
2003-08-06 13:51:03 +00:00
Joel de Guzman
9eb704f85a fixed iteration scheme and added append and extend methods
[SVN r19469]
2003-08-06 08:06:09 +00:00
Dave Abrahams
7754a91929 Update docs for static data support.
[SVN r19462]
2003-08-05 13:41:21 +00:00
Dave Abrahams
e4dc639e54 Allow mutating operations on self for all operators
[SVN r19454]
2003-08-05 03:15:37 +00:00
Ralf W. Grosse-Kunstleve
5d90101671 workaround for MIPSpro, thanks to John Spicer
[SVN r19453]
2003-08-05 03:03:49 +00:00
Ralf W. Grosse-Kunstleve
437fb70852 Tru64 cxx requires X::operator!=
[SVN r19450]
2003-08-05 00:49:33 +00:00
Dave Abrahams
d598404c48 initial commit
[SVN r19449]
2003-08-04 23:52:01 +00:00
Joel de Guzman
32c7088600 added missing typename and include file
[SVN r19448]
2003-08-04 23:34:52 +00:00
Joel de Guzman
ccede29816 added missing line feed at end of source
[SVN r19447]
2003-08-04 23:34:02 +00:00
Ralf W. Grosse-Kunstleve
b55b7e2f7b workaround for Mac OS 10 gcc 3.3 static initialization bug
[SVN r19446]
2003-08-04 22:09:16 +00:00
Ralf W. Grosse-Kunstleve
9217a6a253 avoid (incorrect) Tru64 cxx 6.5.1 warning
[SVN r19445]
2003-08-04 20:54:07 +00:00
Dave Abrahams
07c1319b99 Added the new arg class from
"nickm-at-sitius.com" (Nikolay Mladenov) which supplies the
ability to wrap functions that can be called with ommitted
arguments in the middle.


[SVN r19441]
2003-08-04 17:46:48 +00:00
Dave Abrahams
714b5dc26e missing checkin
[SVN r19439]
2003-08-04 17:36:49 +00:00
Joel de Guzman
1f715958f9 Fixed get_slice
[SVN r19421]
2003-08-04 05:09:23 +00:00
Joel de Guzman
0922aca873 Better usage of handle<>.
[SVN r19420]
2003-08-04 03:24:41 +00:00
Joel de Guzman
30ec6181b5 Fixed negative ref count bug
[SVN r19419]
2003-08-04 02:36:47 +00:00
Dave Abrahams
b28d586612 Move assignment operator inline as a workaround for a vc7 bug.
[SVN r19416]
2003-08-03 14:19:09 +00:00
Dave Abrahams
f48aacf477 added internals
[SVN r19390]
2003-07-31 18:03:17 +00:00
Dave Abrahams
bfa868a440 Workarounds for VC6 bugs
[SVN r19389]
2003-07-31 15:56:10 +00:00
Dave Abrahams
f01ff3a277 Prune #includes
[SVN r19382]
2003-07-31 01:04:51 +00:00
Dave Abrahams
d88e6bf688 object_core.hpp - use detail/is_xxx to generate template identifiers
object_operators.hpp - use SFINAE to prevent ADL from finding
        generalized operators inappropriately


[SVN r19377]
2003-07-30 23:48:06 +00:00
Dave Abrahams
a3cdacd088 Bug fix -- we weren't handling NULL keywords dictionaries in raw_function
[SVN r19359]
2003-07-30 11:34:50 +00:00
Joel de Guzman
81d99c855f Minor tweaks
[SVN r19335]
2003-07-29 04:47:34 +00:00
Joel de Guzman
5cd110f625 Comments from Dave + Editing + Proof reading and stuff
[SVN r19334]
2003-07-29 04:30:37 +00:00
Joel de Guzman
416895ff30 linked in the indexing suite documentation
[SVN r19315]
2003-07-26 05:49:57 +00:00
Joel de Guzman
e41abb6e92 Initial commit of indexing suite documentation
[SVN r19314]
2003-07-26 05:48:59 +00:00
Joel de Guzman
a6440a3fa6 Minor tweaks
[SVN r19313]
2003-07-26 05:47:11 +00:00
Joel de Guzman
2dece7ecaf added __iter__ and __contains__
[SVN r19311]
2003-07-26 01:50:35 +00:00
Dave Abrahams
7aae525587 Added RationalDiscovery
[SVN r19300]
2003-07-24 16:38:23 +00:00
Ralf W. Grosse-Kunstleve
ac5314093b fixing some trivial bugs (missing or misplaced typename); work around gcc 3.2 bug
[SVN r19299]
2003-07-24 15:07:05 +00:00
Ralf W. Grosse-Kunstleve
1524fb9fa9 flotsam removed
[SVN r19297]
2003-07-24 13:51:06 +00:00
Joel de Guzman
957549460b Initial Commit of Indexing Suite
[SVN r19296]
2003-07-24 12:02:57 +00:00
Joel de Guzman
3b33f54fb8 Added generic visitation mechanism.
[SVN r19288]
2003-07-24 01:44:18 +00:00
Ralf W. Grosse-Kunstleve
42ab6b6b66 unused variable removed (to avoid MIPSpro warning)
[SVN r19287]
2003-07-23 19:00:55 +00:00
Dave Abrahams
f59a5bbabc Stop printing return types in error messages.
[SVN r19286]
2003-07-23 17:04:05 +00:00
Dave Abrahams
0be371d747 Added cross-module exception test
[SVN r19282]
2003-07-23 15:17:03 +00:00
Dave Abrahams
2b52210291 remove (again!) extra diagnostic info
[SVN r19281]
2003-07-23 14:14:00 +00:00
Dave Abrahams
96a7bce78e Give feedback about the name and namespace of functions in error messages.
[SVN r19280]
2003-07-23 13:08:59 +00:00
Dave Abrahams
c1e1ea697c Added Metafaq link
[SVN r19278]
2003-07-23 11:43:06 +00:00
Dave Abrahams
874d6ebf2c Kill off nasty diagnostic printing.
[SVN r19277]
2003-07-23 11:11:56 +00:00
Dave Abrahams
77f5eb703c Attempt to work around a GCC EH problem by sticking a virtual function
in error_already_set and defining it in the library.

Removed some flotsam


[SVN r19274]
2003-07-23 03:00:48 +00:00
Dave Abrahams
af53ae8329 Implemented better error reporting for argument match errors.
[SVN r19271]
2003-07-23 01:31:34 +00:00
Dave Abrahams
8f76b8880e Remove bad #includes
[SVN r19269]
2003-07-22 23:55:09 +00:00
Dave Abrahams
fa398734be initial commit
[SVN r19267]
2003-07-22 23:53:06 +00:00
Dave Abrahams
362d20a8c7 Fixed editing error
[SVN r19265]
2003-07-22 20:12:39 +00:00
Dave Abrahams
6a33b8aeeb Implemented better error reporting for argument match errors.
[SVN r19264]
2003-07-22 20:12:07 +00:00
Dave Abrahams
d4e06ac436 Preparation for delivering nicely-formatted error messages in
Boost.Python.  The major change is that, instead of being
boost::function2<PyObject*,PyObject*,PyObject*>, py_function is now a
runtime-polymorphic wrapper for compile-time polymorphic
behavior (just like function) of our own which carries more
information/behaviors.  In particular, you can retrieve an array of
c-strings describing the types in the function signature.
Additionally, the minimum and maximum arity are stored in the
py_function object instead of in the 'function' object which wraps it.

* data_members.hpp -

     Adjustments for the new py_function.  Workarounds for CodeWarrior
     Pro 8.3 bugs in function template argument deduction with
     pointers-to-members.

* has_back_reference.hpp, test/back_reference.cpp,
  test/select_holder.cpp -

     Updated to follow the metafunction protocol

* init.hpp, detail/defaults_gen.hpp -

     Make Keywords a more-specific type in function signatures to
     prevent string literals that show up as char[N] from binding to
     the wrong argument (at least Intel 7.1 for Windows does this).

* make_function.hpp -

     Adjustments for the new py_function.  Arities are now computed
     by caller<>.

* opaque_pointer_converter.hpp, type_id.hpp -

     Use BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS facilities;
     generate specializations that all compilers can handle.

* raw_function.hpp -

     Adjustments for the new py_function.

* caller.hpp -

     Added arity and signature type name reporting.

* detail/config.hpp

     Enable __declspec(dllexport) for Cygwin, thereby fixing the
     recent horrible Cygwin linking problems.


* detail/msvc_typeinfo.hpp -

     Always pass boost::type<T>* explicitly, thereby working around
     incompatible notions of how to specialize function templates with
     default arguments on various compilers.

*   object/function.hpp
  , object/function_handle.hpp
  , object/function_object.hpp
  , object/function_object.cpp

     Adjustments for the new py_function.  Arities are carried by
     py_function.

* object/iterator.hpp, object/iterator.cpp

     Adjustments for the new py_function; we have to compute a
     signature of types to construct it with.

* object/py_function.hpp

     Removed dependency on boost::function; see the comment at the
     top of this entry for more details.

* object/select_holder.hpp

     Clean up to more closely follow MPL idioms.

* test/Jamfile -

     Adjust the embedding test for the new Cygwin use of declspec.
     Update bases and pointee tests with missing properties.

* test/input_iterator.cpp -

     Updates for the new iterator adaptors.

* test/opaque.py -

     Add Python encoding comment to suppress PendinDeprecationWarning
     with recent Python builds.

* test/str.cpp

     Pass a Python long instead of a float to string.expandtabs,
     suppressing a PendinDeprecationWarning with recent Python builds.

* libs/utility/counting_iterator_example.cpp

     Borland workaround

* libs/utility/indirect_iterator_example.cpp

     const-correctness fix.

*


[SVN r19247]
2003-07-22 00:06:41 +00:00
Dave Abrahams
817dcd37e0 Get Cygwin linking again
User-readable type name printing for GCC


[SVN r19236]
2003-07-21 02:14:58 +00:00
Dave Abrahams
25bfd3c50f Suppress a GCC 2.x ICE
[SVN r19235]
2003-07-21 02:12:04 +00:00
Dave Abrahams
b13c902fb0 * added return_arg policy from Nikolay Mladenov
* removed duplication from reference.html

* improved automatic redirection messages


[SVN r19226]
2003-07-19 23:49:06 +00:00
Dave Abrahams
c95ef44b02 Added Kig
[SVN r19154]
2003-07-16 15:40:27 +00:00
Bruno da Silva de Oliveira
162727590c - moved register_ptr_to_python up one level.
[SVN r19123]
2003-07-15 01:05:07 +00:00
Vladimir Prus
7e159844fb Update for current Boost.Build V2.
[SVN r19037]
2003-07-11 06:04:35 +00:00
Dave Abrahams
787b79cc2c Added NeuraLab
[SVN r18979]
2003-07-08 13:10:59 +00:00
31 changed files with 749 additions and 297 deletions

View File

@@ -1,3 +1,25 @@
17 August 2003
Added support for insertion of user code in the generated code.
16 August 2003
Applied a patch by Gottfried Ganssauge that adds exception specifiers to
wrapper functions and pointer declarations. Thanks a lot Gottfried!!
Applied a patch by Prabhu Ramachandran that fixes ae problem with the
pure virtual method generation. Thanks again Prabhu!
10 August 2003
Support for incremental generation of the code has been added. This changes
how --multiple works; documentation of this new feature will follow. Thanks
to Prabhu Ramachandran, that saw the need for this feature and discussed a
solution.
Automatically convert \ to / in Windows systems before passing the paths to
gccxml.
Fixed a bug reported by Prabhu Ramachandran, where in some classes the virtual
methods were being definied incorrectly. Thanks a lot Prabhu!
7 July 2003
Applied 2 patches by Prabhu Ramachandran: a fix in the new --multiple method,
and two new functions "hold_with_shared_ptr" and its counterpart for auto_ptr.

View File

@@ -8,3 +8,5 @@
instance)
- Virtual operators
- args() support

View File

@@ -48,25 +48,23 @@ class ClassExporter(Exporter):
return makeid(self.class_.FullName()) + '_scope'
def Unit(self):
return makeid(self.class_.name)
def Name(self):
return self.class_.FullName()
return self.info.name
def SetDeclarations(self, declarations):
Exporter.SetDeclarations(self, declarations)
decl = self.GetDeclaration(self.info.name)
if isinstance(decl, Typedef):
self.class_ = self.GetDeclaration(decl.type.name)
if not self.info.rename:
self.info.rename = decl.name
if self.declarations:
decl = self.GetDeclaration(self.info.name)
if isinstance(decl, Typedef):
self.class_ = self.GetDeclaration(decl.type.name)
if not self.info.rename:
self.info.rename = decl.name
else:
self.class_ = decl
self.class_ = copy.deepcopy(self.class_)
else:
self.class_ = decl
self.class_ = copy.deepcopy(self.class_)
self.class_ = None
def ClassBases(self):
@@ -82,7 +80,8 @@ class ClassExporter(Exporter):
bases' bases. Do this because base classes must be instantialized
before the derived classes in the module definition.
'''
return '%s_%s' % (len(self.ClassBases()), self.class_.FullName())
num_bases = len(self.ClassBases())
return num_bases, self.class_.FullName()
def Export(self, codeunit, exported_names):
@@ -101,7 +100,7 @@ class ClassExporter(Exporter):
self.ExportSmartPointer()
self.ExportOpaquePointerPolicies()
self.Write(codeunit)
exported_names[self.class_.FullName()] = 1
exported_names[self.Name()] = 1
def InheritMethods(self, exported_names):
@@ -111,8 +110,12 @@ class ClassExporter(Exporter):
just export one type and automatically get all the members from the
base classes.
'''
valid_members = (Method, ClassVariable, NestedClass, ClassOperator,
ConverterOperator, ClassEnumeration)
valid_members = (Method, ClassVariable, NestedClass, ClassEnumeration)
# these don't work INVESTIGATE!: (ClassOperator, ConverterOperator)
fullnames = [x.FullName() for x in self.class_]
pointers = [x.PointerDeclaration(True) for x in self.class_ if isinstance(x, Method)]
fullnames = dict([(x, None) for x in fullnames])
pointers = dict([(x, None) for x in pointers])
for level in self.class_.hierarchy:
level_exported = False
for base in level:
@@ -120,17 +123,22 @@ class ClassExporter(Exporter):
if base.FullName() not in exported_names:
for member in base:
if type(member) in valid_members:
member = copy.deepcopy(member)
#if type(member) not in (ClassVariable,:
# member.class_ = self.class_.FullName()
self.class_.AddMember(member)
member_copy = copy.deepcopy(member)
member_copy.class_ = self.class_.FullName()
if isinstance(member_copy, Method):
pointer = member_copy.PointerDeclaration(True)
if pointer not in pointers:
self.class_.AddMember(member)
pointers[pointer] = None
elif member_copy.FullName() not in fullnames:
self.class_.AddMember(member)
else:
level_exported = True
if level_exported:
break
def IsValid(member):
return isinstance(member, valid_members) and member.visibility == Scope.public
self.public_members = [x for x in self.class_ if IsValid(x)]
self.public_members = [x for x in self.class_ if IsValid(x)]
def Write(self, codeunit):
@@ -195,14 +203,9 @@ class ClassExporter(Exporter):
def ExportBasics(self):
'''Export the name of the class and its class_ statement.
Also export the held_type if specified.'''
'''Export the name of the class and its class_ statement.'''
class_name = self.class_.FullName()
self.Add('template', class_name)
held_type = self.info.held_type
if held_type:
held_type = held_type % class_name
self.Add('template', held_type)
name = self.info.rename or self.class_.name
self.Add('constructor', '"%s"' % name)
@@ -210,14 +213,14 @@ class ClassExporter(Exporter):
def ExportBases(self, exported_names):
'Expose the bases of the class into the template section'
hierarchy = self.class_.hierarchy
exported = []
for level in hierarchy:
exported = []
for base in level:
if base.visibility == Scope.public and base.name in exported_names:
exported.append(base.name)
if exported:
code = namespaces.python + 'bases< %s > ' % (', '.join(exported))
self.Add('template', code)
if exported:
code = namespaces.python + 'bases< %s > ' % (', '.join(exported))
self.Add('template', code)
def ExportConstructors(self):
@@ -407,13 +410,19 @@ class ClassExporter(Exporter):
has_virtual_methods = True
break
holder = self.info.holder
if has_virtual_methods:
generator = _VirtualWrapperGenerator(self.class_, self.ClassBases(), self.info)
self.Add('template', generator.FullName())
if holder:
self.Add('template', holder(generator.FullName()))
else:
self.Add('template', generator.FullName())
for definition in generator.GenerateDefinitions():
self.Add('inside', definition)
self.Add('declaration', generator.GenerateVirtualWrapper(self.INDENT))
else:
if holder:
self.Add('template', holder(self.class_.FullName()))
# operators natively supported by boost
BOOST_SUPPORTED_OPERATORS = '+ - * / % ^ & ! ~ | < > == != <= >= << >> && || += -='\
@@ -609,7 +618,7 @@ class ClassExporter(Exporter):
if smart_ptr:
class_name = self.class_.FullName()
smart_ptr = smart_ptr % class_name
self.Add('scope', '%s::register_ptr_to_python< %s >();' % (namespaces.python, smart_ptr))
self.Add('scope', '%sregister_ptr_to_python< %s >();' % (namespaces.python, smart_ptr))
def ExportOpaquePointerPolicies(self):
@@ -645,7 +654,7 @@ class _VirtualWrapperGenerator(object):
'Generates code to export the virtual methods of the given class'
def __init__(self, class_, bases, info):
self.class_ = class_
self.class_ = copy.deepcopy(class_)
self.bases = bases[:]
self.info = info
self.wrapper_name = makeid(class_.FullName()) + '_Wrapper'
@@ -686,7 +695,7 @@ class _VirtualWrapperGenerator(object):
constantness = ' const'
# call_method callback
decl = indent + '%s %s(%s)%s {\n' % (result, method.name, params, constantness)
decl = indent + '%s %s(%s)%s%s {\n' % (result, method.name, params, constantness, method.Exceptions())
param_names_str = ', '.join(param_names)
if param_names_str:
param_names_str = ', ' + param_names_str
@@ -697,17 +706,26 @@ class _VirtualWrapperGenerator(object):
# default implementations (with overloading)
def DefaultImpl(method, param_names):
'Return the body of a default implementation wrapper'
indent2 = indent * 2
wrapper = self.info[method.name].wrapper
if not wrapper:
# return the default implementation of the class
return '%s%s(%s);\n' % \
(return_str, method.FullName(), ', '.join(param_names))
if method.abstract:
s = indent2 + 'PyErr_SetString(PyExc_RuntimeError, "pure virtual function called");\n' +\
indent2 + 'throw_error_already_set();\n'
params = ', '.join(param_names)
s += indent2 + '%s%s(%s);\n' % \
(return_str, method.name, params)
return s
else:
return indent2 + '%s%s(%s);\n' % \
(return_str, method.FullName(), ', '.join(param_names))
else:
# return a call for the wrapper
params = ', '.join(['this'] + param_names)
return '%s%s(%s);\n' % (return_str, wrapper.FullName(), params)
return indent2 + '%s%s(%s);\n' % (return_str, wrapper.FullName(), params)
if not method.abstract and method.visibility != Scope.private:
if method.visibility != Scope.private:
minArgs = method.minArgs
maxArgs = method.maxArgs
impl_names = self.DefaultImplementationNames(method)
@@ -715,7 +733,7 @@ class _VirtualWrapperGenerator(object):
params, param_names, param_types = _ParamsInfo(method, argNum)
decl += '\n'
decl += indent + '%s %s(%s)%s {\n' % (result, impl_name, params, constantness)
decl += indent*2 + DefaultImpl(method, param_names)
decl += DefaultImpl(method, param_names)
decl += indent + '}\n'
return decl
@@ -780,21 +798,14 @@ class _VirtualWrapperGenerator(object):
return type(m) is Method and \
m.virtual and \
m.visibility != Scope.private
all_methods = [x for x in self.class_ if IsVirtual(x)]
for base in self.bases:
base_methods = [copy.deepcopy(x) for x in base if IsVirtual(x)]
for base_method in base_methods:
base_method.class_ = self.class_.FullName()
all_methods.append(base_method)
# extract the virtual methods, avoiding duplications. The duplication
# must take in account the full signature without the class name, so
# that inherited members are correctly excluded if the subclass overrides
# them.
def MethodSig(method):
if method.const:
const = 'const'
const = ' const'
else:
const = ''
if method.result:
@@ -802,10 +813,23 @@ class _VirtualWrapperGenerator(object):
else:
result = ''
params = ', '.join([x.FullName() for x in method.parameters])
return '%s %s(%s) %s' % (result, method.name, params, const)
self.virtual_methods = []
return '%s %s(%s)%s%s' % (
result, method.name, params, const, method.Exceptions())
already_added = {}
self.virtual_methods = []
for member in self.class_:
if IsVirtual(member):
already_added[MethodSig(member)] = None
self.virtual_methods.append(member)
for base in self.bases:
base_methods = [copy.deepcopy(x) for x in base if IsVirtual(x)]
for base_method in base_methods:
self.class_.AddMember(base_method)
all_methods = [x for x in self.class_ if IsVirtual(x)]
for member in all_methods:
sig = MethodSig(member)
if IsVirtual(member) and not sig in already_added:
@@ -822,7 +846,7 @@ class _VirtualWrapperGenerator(object):
for method in self.virtual_methods:
exclude = self.info[method.name].exclude
# generate definitions only for public methods and non-abstract methods
if method.visibility == Scope.public and not method.abstract and not exclude:
if method.visibility == Scope.public and not exclude:
defs.extend(self.MethodDefinition(method))
return defs

View File

@@ -0,0 +1,21 @@
from Exporter import Exporter
#==============================================================================
# CodeExporter
#==============================================================================
class CodeExporter(Exporter):
def __init__(self, info):
Exporter.__init__(self, info)
def Name(self):
return self.info.code
def Export(self, codeunit, exported_names):
codeunit.Write(self.info.section, self.info.code)
def WriteInclude(self, codeunit):
pass

View File

@@ -2,16 +2,25 @@ from GCCXMLParser import ParseDeclarations
import tempfile
import shutil
import os
import sys
import os.path
import settings
import shutil
import shelve
from cPickle import dump, load
#==============================================================================
# exceptions
#==============================================================================
class CppParserError(Exception): pass
#==============================================================================
# CppParser
#==============================================================================
class CppParser:
'Parses a header file and returns a list of declarations'
def __init__(self, includes=None, defines=None):
def __init__(self, includes=None, defines=None, cache_dir=None):
'includes and defines ar the directives given to gcc'
if includes is None:
includes = []
@@ -19,9 +28,27 @@ class CppParser:
defines = []
self.includes = includes
self.defines = defines
#if cache_dir is None:
# cache_dir = tempfile.mktemp()
# self.delete_cache = True
#else:
# self.delete_cache = False
self.delete_cache = False
self.cache_dir = cache_dir
self.cache_files = []
self.mem_cache = {}
# create the cache dir
if cache_dir:
try:
os.makedirs(cache_dir)
except OSError: pass
def _includeparams(self, filename):
def __del__(self):
self.Close()
def _IncludeParams(self, filename):
includes = self.includes[:]
filedir = os.path.dirname(filename)
if not filedir:
@@ -31,64 +58,164 @@ class CppParser:
return ' '.join(includes)
def _defineparams(self):
def _DefineParams(self):
defines = ['-D "%s"' % x for x in self.defines]
return ' '.join(defines)
def FindFileName(self, include):
if os.path.isfile(include):
return include
def FindHeader(self, header):
if os.path.isfile(header):
return header
for path in self.includes:
filename = os.path.join(path, include)
filename = os.path.join(path, header)
if os.path.isfile(filename):
return filename
name = os.path.basename(include)
raise RuntimeError, 'Header file "%s" not found!' % name
else:
name = os.path.basename(header)
raise RuntimeError, 'Header file "%s" not found!' % name
def parse(self, include, tail=None, decl_name=None):
'''Parses the given filename, and returns (declaration, header). The
header returned is normally the same as the given to this method,
except if tail is not None: in this case, the header is copied to a temp
filename and the tail code is appended to it before being passed on to gcc.
This temp filename is then returned.
'''
filename = self.FindFileName(include)
# copy file to temp folder, if needed
def AppendTail(self, filename, tail):
'''Creates a temporary file, appends the text tail to it, and returns
the filename of the file.
'''
temp = tempfile.mktemp('.h')
shutil.copyfile(filename, temp)
f = file(temp, 'a')
f.write('\n\n'+tail)
f.close()
return temp
def ParseWithGCCXML(self, header, tail):
'''Parses the given header using gccxml and GCCXMLParser.
'''
header = self.FindHeader(header)
if tail:
tempfilename = tempfile.mktemp('.h')
infilename = tempfilename
shutil.copyfile(filename, infilename)
f = file(infilename, 'a')
f.write('\n\n'+tail)
f.close()
filename = self.AppendTail(header, tail)
else:
infilename = filename
filename = header
xmlfile = tempfile.mktemp('.xml')
try:
# get the params
includes = self._includeparams(filename)
defines = self._defineparams()
includes = self._IncludeParams(filename)
defines = self._DefineParams()
# call gccxml
cmd = 'gccxml %s %s %s -fxml=%s' \
% (includes, defines, infilename, xmlfile)
if decl_name is not None:
cmd += ' "-fxml-start=%s"' % decl_name
status = os.system(cmd)
cmd = 'gccxml %s %s %s -fxml=%s'
status = os.system(cmd % (includes, defines, filename, xmlfile))
if status != 0 or not os.path.isfile(xmlfile):
raise CppParserError, 'Error executing gccxml'
# parse the resulting xml
declarations = ParseDeclarations(xmlfile)
# make the declarations' location to point to the original file
if tail:
for decl in declarations:
decl_filename = os.path.normpath(os.path.normcase(decl.location[0]))
filename = os.path.normpath(os.path.normcase(filename))
if decl_filename == filename:
decl.location = header, decl.location[1]
# return the declarations
return declarations, infilename
return declarations
finally:
if settings.DEBUG and os.path.isfile(xmlfile):
filename = os.path.basename(include)
shutil.copy(xmlfile, os.path.splitext(filename)[0] + '.xml')
filename = os.path.basename(header)
filename = os.path.splitext(filename)[0] + '.xml'
shutil.copy(xmlfile, filename)
# delete the temporary files
try:
os.remove(xmlfile)
if tail:
os.remove(tempfilename)
except OSError: pass
os.remove(filename)
except OSError: pass
def Parse(self, header, interface, tail=None):
'''Parses the given filename related to the given interface and returns
the (declarations, headerfile). The header returned is normally the
same as the given to this method (except that it is the full path),
except if tail is not None: in this case, the header is copied to a temp
filename and the tail code is appended to it before being passed on to
gccxml. This temp filename is then returned.
'''
if tail is None:
tail = ''
tail.strip()
declarations = self.GetCache(header, interface, tail)
if declarations is None:
declarations = self.ParseWithGCCXML(header, tail)
self.CreateCache(header, interface, tail, declarations)
return declarations, header
def CacheFileName(self, interface):
interface_name = os.path.basename(interface)
cache_file = os.path.splitext(interface_name)[0] + '.pystec'
cache_file = os.path.join(self.cache_dir, cache_file)
return cache_file
def GetCache(self, header, interface, tail):
key = (header, interface, tail)
# try memory cache first
if key in self.mem_cache:
return self.mem_cache[key]
# get the cache from the disk
if self.cache_dir is None:
return None
header = self.FindHeader(header)
cache_file = self.CacheFileName(interface)
if os.path.isfile(cache_file):
f = file(cache_file, 'rb')
try:
cache = load(f)
if cache.has_key(key):
self.cache_files.append(cache_file)
return cache[key]
else:
return None
finally:
f.close()
else:
return None
def CreateCache(self, header, interface, tail, declarations):
key = (header, interface, tail)
# our memory cache only holds one item
self.mem_cache.clear()
self.mem_cache[key] = declarations
# save the cache in the disk
if self.cache_dir is None:
return
header = self.FindHeader(header)
cache_file = self.CacheFileName(interface)
if os.path.isfile(cache_file):
f = file(cache_file, 'rb')
try:
cache = load(f)
finally:
f.close()
else:
cache = {}
cache[key] = declarations
self.cache_files.append(cache_file)
f = file(cache_file, 'wb')
try:
dump(cache, f, 1)
finally:
f.close()
return cache_file
def Close(self):
if self.delete_cache and self.cache_files:
for filename in self.cache_files:
try:
os.remove(filename)
except OSError:
pass
self.cache_files = []
shutil.rmtree(self.cache_dir)

View File

@@ -14,7 +14,10 @@ class EnumExporter(Exporter):
def SetDeclarations(self, declarations):
Exporter.SetDeclarations(self, declarations)
self.enum = self.GetDeclaration(self.info.name)
if self.declarations:
self.enum = self.GetDeclaration(self.info.name)
else:
self.enum = None
def Export(self, codeunit, exported_names):
@@ -34,12 +37,8 @@ class EnumExporter(Exporter):
code += in_indent + '.value("%s", %s)\n' % (rename, value_fullname)
code += indent + ';\n\n'
codeunit.Write('module', code)
exported_names[self.enum.FullName()] = 1
exported_names[self.Name()] = 1
def Unit(self):
return utils.makeid(self.info.include)
def Order(self):
def Name(self):
return self.info.name

View File

@@ -12,10 +12,11 @@ class Exporter(object):
self.info = info
self.parser_tail = parser_tail
self.interface_file = None
self.declarations = []
def Name(self):
return self.info.name
raise NotImplementedError(self.__class__.__name__)
def Tail(self):
@@ -73,12 +74,15 @@ class Exporter(object):
'''Returns a string that uniquely identifies this instance. All
exporters will be sorted by Order before being exported.
'''
raise NotImplementedError
def Unit(self):
return self.info.include
return 0, self.info.name
def Header(self):
return self.info.include
def __eq__(self, other):
return self.Name() == other.Name()
def __ne__(self, other):
return self.Name() != other.Name()

View File

@@ -24,7 +24,7 @@ class FunctionExporter(Exporter):
self.ExportDeclaration(decl, len(decls) == 1, codeunit)
self.ExportOpaquePointer(decl, codeunit)
self.GenerateOverloads(decls, codeunit)
exported_names[decl.FullName()] = 1
exported_names[self.Name()] = 1
def ExportDeclaration(self, decl, unique, codeunit):
@@ -44,7 +44,7 @@ class FunctionExporter(Exporter):
codeunit.Write('module', self.INDENT + defs + '\n')
# add the code of the wrapper
if wrapper and wrapper.code:
codeunit.Write('declaration', code + '\n')
codeunit.Write('declaration', wrapper.code + '\n')
def OverloadName(self, decl):
@@ -82,9 +82,6 @@ class FunctionExporter(Exporter):
if macro:
codeunit.Write('declaration-outside', macro)
def Order(self):
def Name(self):
return self.info.name
def Unit(self):
return utils.makeid(self.info.include)

View File

@@ -193,6 +193,17 @@ class GCCXMLParser(object):
return args
def GetExceptions(self, exception_list):
if exception_list is None:
return None
exceptions = []
for t in exception_list.split():
exceptions.append(self.GetType(t))
return exceptions
def ParseFunction(self, id, element, functionType=Function):
'''functionType is used because a Operator is identical to a normal
function, only the type of the function changes.'''
@@ -202,7 +213,8 @@ class GCCXMLParser(object):
location = self.GetLocation(element.get('location'))
params = self.GetArguments(element)
incomplete = bool(int(element.get('incomplete', 0)))
function = functionType(name, namespace, returns, params)
throws = self.GetExceptions(element.get('throw', None))
function = functionType(name, namespace, returns, params, throws)
function.location = location
self.AddDecl(function)
self.Update(id, function)
@@ -366,9 +378,10 @@ class GCCXMLParser(object):
abstract = bool(int(element.get('pure_virtual', '0')))
const = bool(int(element.get('const', '0')))
location = self.GetLocation(element.get('location'))
throws = self.GetExceptions(element.get('throw', None))
params = self.GetArguments(element)
method = methodType(
name, classname, result, params, visib, virtual, abstract, static, const)
name, classname, result, params, visib, virtual, abstract, static, const, throws)
method.location = location
self.Update(id, method)

View File

@@ -66,17 +66,11 @@ class HeaderExporter(Exporter):
exporter.SetDeclarations(self.declarations)
exporter.SetParsedHeader(self.parser_header)
if isinstance(codeunit, MultipleCodeUnit.MultipleCodeUnit):
codeunit.SetCurrent(self.interface_file, exporter.Unit())
codeunit.SetCurrent(self.interface_file, exporter.Name())
else:
codeunit.SetCurrent(exporter.Unit())
codeunit.SetCurrent(exporter.Name())
exporter.GenerateCode(codeunit, exported_names)
def Unit(self):
return None # doesn't write anything by itself
def Order(self):
def Name(self):
return self.info.include

View File

@@ -1,27 +0,0 @@
import os.path
from Exporter import Exporter
#==============================================================================
# IncludeExporter
#==============================================================================
class IncludeExporter(Exporter):
'''Writes an include declaration to the module. Useful to add extra code
for use in the Wrappers.
This class just reimplements the Parse method to do nothing: the
WriteInclude in Exporter already does the work for us.
'''
def __init__(self, info, parser_tail=None):
Exporter.__init__(self, info, parser_tail)
def Parse(self, parser):
pass
def Order(self):
return self.info.include
def Unit(self):
return '__all__' # include it in all generated cpps (multiple mode)
def Header(self):
return None # means "don't try to parse me!"

View File

@@ -22,8 +22,9 @@ class MultipleCodeUnit(object):
self.all = SingleCodeUnit(None, None)
def _FunctionName(self, export_name):
return 'Export_%s' % utils.makeid(export_name)
def _FunctionName(self, interface_file):
name = os.path.splitext(interface_file)[0]
return 'Export_%s' % utils.makeid(name)
def _FileName(self, interface_file):
@@ -40,13 +41,13 @@ class MultipleCodeUnit(object):
self._current = self.all
else:
filename = self._FileName(interface_file)
function = self._FunctionName(export_name)
function = self._FunctionName(interface_file)
try:
codeunit = self.codeunits[(filename, function)]
codeunit = self.codeunits[filename]
except KeyError:
codeunit = SingleCodeUnit(None, filename)
codeunit.module_definition = 'void %s()' % function
self.codeunits[(filename, function)] = codeunit
self.codeunits[filename] = codeunit
if function not in self.functions:
self.functions.append(function)
self._current = codeunit
@@ -84,7 +85,7 @@ class MultipleCodeUnit(object):
# unit in the list of code units is used as the main unit
# which dumps all the include, declaration and
# declaration-outside sections at the top of the file.
for (filename, _), codeunit in self.codeunits.items():
for filename, codeunit in self.codeunits.items():
if filename not in codeunits:
# this codeunit is the main codeunit.
codeunits[filename] = [codeunit]
@@ -103,20 +104,24 @@ class MultipleCodeUnit(object):
codeunit.Save(append)
if not append:
append = True
def GenerateMain(self, interfaces):
# generate the main cpp
filename = os.path.join(self.outdir, '_main.cpp')
fout = SmartFile(filename, 'w')
fout.write(utils.left_equals('Include'))
fout.write('#include <boost/python.hpp>\n\n')
fout.write('#include <boost/python/module.hpp>\n\n')
fout.write(utils.left_equals('Exports'))
for function in self.functions:
functions = [self._FunctionName(x) for x in interfaces]
for function in functions:
fout.write('void %s();\n' % function)
fout.write('\n')
fout.write(utils.left_equals('Module'))
fout.write('BOOST_PYTHON_MODULE(%s)\n' % self.modulename)
fout.write('{\n')
indent = ' ' * 4
for function in self.functions:
for function in functions:
fout.write(indent)
fout.write('%s();\n' % function)
fout.write('}\n')

View File

@@ -50,7 +50,7 @@ class SingleCodeUnit:
return self.code[section]
def SetCurrent(self, current):
def SetCurrent(self, *args):
pass
@@ -85,13 +85,14 @@ class SingleCodeUnit:
fout.write(declaration_outside + '\n\n')
if declaration:
pyste_namespace = namespaces.pyste[:-2]
fout.write('namespace %s {\n\n\n' % pyste_namespace)
fout.write('namespace %s {\n\n' % pyste_namespace)
fout.write(declaration)
fout.write('\n\n}// namespace %s\n' % pyste_namespace)
fout.write('\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')
fout.write('}\n\n')
fout.close()

View File

@@ -28,8 +28,8 @@ class VarExporter(Exporter):
def Order(self):
return 0, self.info.name
def Name(self):
return self.info.name
def Unit(self):
return utils.makeid(self.info.include)

View File

@@ -123,7 +123,7 @@ class Class(Declaration):
m.is_unique = False
else:
member.is_unique = True
self.__member_names[member.name] = 1
self.__member_names[member.name] = 1
self.__members.append(member)
if isinstance(member, ClassOperator):
self.operator[member.name] = member
@@ -196,14 +196,24 @@ class Function(Declaration):
'''The declaration of a function.
@ivar _result: instance of L{Type} or None.
@ivar _parameters: list of L{Type} instances.
@ivar _throws: exception specifiers or None
'''
def __init__(self, name, namespace, result, params):
def __init__(self, name, namespace, result, params, throws=None):
Declaration.__init__(self, name, namespace)
# the result type: instance of Type, or None (constructors)
self.result = result
# the parameters: instances of Type
self.parameters = params
# the exception specification
self.throws = throws
def Exceptions(self):
if self.throws is None:
return ""
else:
return " throw(%s)" % ', '.join (self.throws)
def PointerDeclaration(self, force=False):
@@ -264,10 +274,11 @@ class Method(Function):
@ivar _static: if this method is static.
@ivar _class: the full name of the class where this method was declared.
@ivar _const: if this method is declared as const.
@ivar _throws: list of exception specificiers or None
'''
def __init__(self, name, class_, result, params, visib, virtual, abstract, static, const):
Function.__init__(self, name, None, result, params)
def __init__(self, name, class_, result, params, visib, virtual, abstract, static, const, throws=None):
Function.__init__(self, name, None, result, params, throws)
self.visibility = visib
self.virtual = virtual
self.abstract = abstract
@@ -296,8 +307,8 @@ class Method(Function):
const = ''
if self.const:
const = 'const'
return '(%s (%s::*)(%s) %s)&%s' %\
(result, self.class_, params, const, self.FullName())
return '(%s (%s::*)(%s) %s%s)&%s' %\
(result, self.class_, params, const, self.Exceptions(), self.FullName())
#==============================================================================
@@ -329,6 +340,10 @@ class Constructor(Method):
return param_reference and class_as_param and param.const and is_public
def PointerDeclaration(self, force=False):
return ''
#==============================================================================
# Destructor
#==============================================================================
@@ -342,6 +357,10 @@ class Destructor(Method):
return self.class_ + '::~' + self.name
def PointerDeclaration(self, force=False):
return ''
#==============================================================================
# ClassOperator

View File

@@ -7,6 +7,7 @@ from IncludeExporter import IncludeExporter
from EnumExporter import EnumExporter
from HeaderExporter import HeaderExporter
from VarExporter import VarExporter
from CodeExporter import CodeExporter
from exporterutils import FunctionWrapper
from utils import makeid
@@ -58,7 +59,8 @@ class FunctionInfo(DeclarationInfo):
self._Attribute('exclude', False)
# create a FunctionExporter
exporter = FunctionExporter(InfoWrapper(self), tail)
exporters.exporters.append(exporter)
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
@@ -74,23 +76,11 @@ class ClassInfo(DeclarationInfo):
self._Attribute('exclude', False)
# create a ClassExporter
exporter = ClassExporter(InfoWrapper(self), tail)
exporters.exporters.append(exporter)
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
#==============================================================================
# IncludeInfo
#==============================================================================
class IncludeInfo(DeclarationInfo):
def __init__(self, include):
DeclarationInfo.__init__(self)
self._Attribute('include', include)
exporter = IncludeExporter(InfoWrapper(self))
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
#==============================================================================
# templates
#==============================================================================
@@ -137,7 +127,8 @@ class EnumInfo(DeclarationInfo):
self._Attribute('include', include)
self._Attribute('exclude', False)
exporter = EnumExporter(InfoWrapper(self))
exporters.exporters.append(exporter)
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
@@ -150,7 +141,8 @@ class HeaderInfo(DeclarationInfo):
DeclarationInfo.__init__(self)
self._Attribute('include', include)
exporter = HeaderExporter(InfoWrapper(self))
exporters.exporters.append(exporter)
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
@@ -164,10 +156,26 @@ class VarInfo(DeclarationInfo):
self._Attribute('name', name)
self._Attribute('include', include)
exporter = VarExporter(InfoWrapper(self))
exporters.exporters.append(exporter)
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
#==============================================================================
# CodeInfo
#==============================================================================
class CodeInfo(DeclarationInfo):
def __init__(self, code, section):
DeclarationInfo.__init__(self)
self._Attribute('code', code)
self._Attribute('section', section)
exporter = CodeExporter(InfoWrapper(self))
if exporter not in exporters.exporters:
exporters.exporters.append(exporter)
exporter.interface_file = exporters.current_interface
#==============================================================================
# InfoWrapper
#==============================================================================
@@ -215,11 +223,10 @@ def use_shared_ptr(info):
def use_auto_ptr(info):
info._Attribute('smart_ptr', 'std::auto_ptr< %s >')
def hold_with_shared_ptr(info):
info._Attribute('held_type', 'boost::shared_ptr< %s >')
def hold_with_auto_ptr(info):
info._Attribute('held_type', 'std::auto_ptr< %s >')
def holder(info, function):
msg = "Expected a callable that accepts one string argument."
assert callable(function), msg
info._Attribute('holder', function)
def add_method(info, name, rename=None):
added = info._Attribute('__added__')

View File

@@ -1,17 +0,0 @@
import profile
import pstats
import pyste
import psyco
import elementtree.XMLTreeBuilder as XMLTreeBuilder
import GCCXMLParser
if __name__ == '__main__':
#psyco.bind(XMLTreeBuilder.fixtext)
#psyco.bind(XMLTreeBuilder.fixname)
#psyco.bind(XMLTreeBuilder.TreeBuilder)
#psyco.bind(GCCXMLParser.GCCXMLParser)
profile.run('pyste.Main()', 'profile')
p = pstats.Stats('profile')
p.strip_dirs().sort_stats(-1).print_stats()

View File

@@ -1,28 +1,31 @@
'''
"""
Pyste version %s
Usage:
pyste [options] interface-files
where options are:
--module=<name> the name of the module that will be generated.
Defaults to the first interface filename, without
the extension.
-I <path> add an include path
-D <symbol> define symbol
--multiple create various cpps, instead of only one
(useful during development)
--out specify output filename (default: <module>.cpp)
in --multiple mode, this will be a directory
--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 the empty namespace
--debug writes the xml for each file parsed in the current
directory
-h, --help print this help and exit
-v, --version print version information
'''
--module=<name> The name of the module that will be generated;
defaults to the first interface filename, without
the extension.
-I <path> Add an include path
-D <symbol> Define symbol
--multiple Create various cpps, instead of only one
(useful during development)
--out=<name> Specify output filename (default: <module>.cpp)
in --multiple mode, this will be a directory
--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 the empty namespace
--debug Writes the xml for each file parsed in the current
directory
--cache-dir=<dir> Directory for cache files (speeds up future runs)
--only-create-cache Recreates all caches (doesn't generate code).
--generate-main Generates the _main.cpp file (in multiple mode)
-h, --help Print this help and exit
-v, --version Print version information
"""
import sys
import os
@@ -38,8 +41,9 @@ import sys
from policies import *
from CppParser import CppParser, CppParserError
import time
from declarations import Typedef
__VERSION__ = '0.9.10'
__version__ = '0.9.16'
def RecursiveIncludes(include):
'Return a list containg the include dir and all its subdirectories'
@@ -60,26 +64,40 @@ def GetDefaultIncludes():
return []
def ProcessIncludes(includes):
if sys.platform == 'win32':
index = 0
for include in includes:
includes[index] = include.replace('\\', '/')
index += 1
def ParseArguments():
def Usage():
print __doc__ % __VERSION__
print __doc__ % __version__
sys.exit(1)
try:
options, files = getopt.getopt(
sys.argv[1:],
'R:I:D:vh',
['module=', 'multiple', 'out=', 'no-using', 'pyste-ns=', 'debug', 'version', 'help'])
['module=', 'multiple', 'out=', 'no-using', 'pyste-ns=', 'debug', 'cache-dir=',
'only-create-cache', 'version', 'generate-main', 'help'])
except getopt.GetoptError, e:
print
print 'ERROR:', e
Usage()
includes = GetDefaultIncludes()
defines = []
module = None
out = None
multiple = False
cache_dir = None
create_cache = False
generate_main = False
for opt, value in options:
if opt == '-I':
includes.append(value)
@@ -100,11 +118,17 @@ def ParseArguments():
settings.DEBUG = True
elif opt == '--multiple':
multiple = True
elif opt == '--cache-dir':
cache_dir = value
elif opt == '--only-create-cache':
create_cache = True
elif opt in ['-h', '--help']:
Usage()
elif opt in ['-v', '--version']:
print 'Pyste version %s' % __VERSION__
print 'Pyste version %s' % __version__
sys.exit(2)
elif opt == '--generate-main':
generate_main = True
else:
print 'Unknown option:', opt
Usage()
@@ -122,16 +146,28 @@ def ParseArguments():
if d not in sys.path:
sys.path.append(d)
return includes, defines, module, out, files, multiple
if create_cache and not cache_dir:
print 'Error: Use --cache-dir to indicate where to create the cache files!'
Usage()
sys.exit(3)
if generate_main and not multiple:
print 'Error: --generate-main only valid in multiple mode.'
Usage()
sys.exit(3)
ProcessIncludes(includes)
return includes, defines, module, out, files, multiple, cache_dir, create_cache, generate_main
def CreateContext():
'create the context where a interface file will be executed'
context = {}
context['Import'] = ExecuteInterface
# infos
context['Function'] = infos.FunctionInfo
context['Class'] = infos.ClassInfo
context['Include'] = infos.IncludeInfo
context['Include'] = lambda header: infos.CodeInfo('#include <%s>\n' % header, 'include')
context['Template'] = infos.ClassTemplateInfo
context['Enum'] = infos.EnumInfo
context['AllFromHeader'] = infos.HeaderInfo
@@ -143,8 +179,7 @@ def CreateContext():
context['set_wrapper'] = infos.set_wrapper
context['use_shared_ptr'] = infos.use_shared_ptr
context['use_auto_ptr'] = infos.use_auto_ptr
context['hold_with_shared_ptr'] = infos.hold_with_shared_ptr
context['hold_with_auto_ptr'] = infos.hold_with_auto_ptr
context['holder'] = infos.holder
context['add_method'] = infos.add_method
context['final'] = infos.final
# policies
@@ -158,77 +193,166 @@ def CreateContext():
context['manage_new_object'] = manage_new_object
# utils
context['Wrapper'] = exporterutils.FunctionWrapper
context['declaration_code'] = lambda code: infos.CodeInfo(code, 'declaration')
context['global_declaration_code'] = lambda code: infos.CodeInfo(code, 'declaration-outside')
context['module_code'] = lambda code: infos.CodeInfo(code, 'module')
return context
def Begin():
includes, defines, module, out, interfaces, multiple = ParseArguments()
# execute the interface files
# parse arguments
includes, defines, module, out, interfaces, multiple, cache_dir, create_cache, generate_main = ParseArguments()
# run pyste scripts
for interface in interfaces:
exporters.current_interface = interface
context = CreateContext()
execfile(interface, context)
ExecuteInterface(interface)
# create the parser
parser = CppParser(includes, defines)
parser = CppParser(includes, defines, cache_dir)
try:
if not create_cache:
if not generate_main:
return GenerateCode(parser, module, out, interfaces, multiple)
else:
return GenerateMain(module, out, OrderInterfaces(interfaces))
else:
return CreateCaches(parser)
finally:
parser.Close()
def CreateCaches(parser):
# There is one cache file per interface so we organize the headers
# by interfaces. For each interface collect the tails from the
# exporters sharing the same header.
tails = JoinTails(exporters.exporters)
# now for each interface file take each header, and using the tail
# get the declarations and cache them.
for interface, header in tails:
tail = tails[(interface, header)]
declarations = parser.ParseWithGCCXML(header, tail)
cachefile = parser.CreateCache(header, interface, tail, declarations)
print 'Cached', cachefile
return 0
_imported_count = {} # interface => count
def ExecuteInterface(interface):
old_interface = exporters.current_interface
if not os.path.exists(interface):
if old_interface and os.path.exists(old_interface):
d = os.path.dirname(old_interface)
interface = os.path.join(d, interface)
if not os.path.exists(interface):
raise IOError, "Cannot find interface file %s."%interface
_imported_count[interface] = _imported_count.get(interface, 0) + 1
exporters.current_interface = interface
context = CreateContext()
execfile(interface, context)
exporters.current_interface = old_interface
def JoinTails(exports):
'''Returns a dict of {(interface, header): tail}, where tail is the
joining of all tails of all exports for the header.
'''
tails = {}
for export in exports:
interface = export.interface_file
header = export.Header()
tail = export.Tail() or ''
if (interface, header) in tails:
all_tails = tails[(interface,header)]
all_tails += '\n' + tail
tails[(interface, header)] = all_tails
else:
tails[(interface, header)] = tail
return tails
def OrderInterfaces(interfaces):
interfaces_order = [(_imported_count[x], x) for x in interfaces]
interfaces_order.sort()
interfaces_order.reverse()
return [x for _, x in interfaces_order]
def GenerateMain(module, out, interfaces):
codeunit = MultipleCodeUnit.MultipleCodeUnit(module, out)
codeunit.GenerateMain(interfaces)
return 0
def GenerateCode(parser, module, out, interfaces, multiple):
# prepare to generate the wrapper code
if multiple:
codeunit = MultipleCodeUnit.MultipleCodeUnit(module, out)
else:
codeunit = SingleCodeUnit.SingleCodeUnit(module, out)
# group exporters by header files
groups = {}
for export in exporters.exporters:
header = export.Header()
if header in groups:
groups[header].append(export)
else:
groups[header] = [export]
# stop referencing the exporters here
exports = exporters.exporters
exporters.exporters = None
# export all the exporters in each group, releasing memory as doing so
while len(groups) > 0:
# get the first group
header = groups.keys()[0]
exports = groups[header]
del groups[header]
# gather all tails into one
all_tails = []
for export in exports:
if export.Tail():
all_tails.append(export.Tail())
all_tails = '\n'.join(all_tails)
# parse header (if there's one)
exported_names = dict([(x.Name(), None) for x in exports])
# order the exports
interfaces_order = OrderInterfaces(interfaces)
order = {}
for export in exports:
if export.interface_file in order:
order[export.interface_file].append(export)
else:
order[export.interface_file] = [export]
exports = []
for interface in interfaces_order:
exports.extend(order[interface])
del order
del interfaces_order
# now generate the code in the correct order
#print exported_names
tails = JoinTails(exports)
for i in xrange(len(exports)):
export = exports[i]
interface = export.interface_file
header = export.Header()
if header:
try:
declarations, parsed_header = parser.parse(header, all_tails)
except CppParserError, e:
print>>sys.stderr, '\n\n***', e, ': exitting'
return 2
tail = tails[(interface, header)]
declarations, parsed_header = parser.Parse(header, interface, tail)
else:
declarations = []
parsed_header = None
# first set the declarations and parsed_header for all the exporters
for export in exports:
export.SetDeclarations(declarations)
export.SetParsedHeader(parsed_header)
# sort the exporters by their order
exports = [(x.Order(), x) for x in exports]
exports.sort()
exports = [x for _, x in exports]
# maintain a dict of exported_names for this group
exported_names = {}
for export in exports:
if multiple:
codeunit.SetCurrent(export.interface_file, export.Unit())
export.GenerateCode(codeunit, exported_names)
ExpandTypedefs(declarations, exported_names)
export.SetDeclarations(declarations)
export.SetParsedHeader(parsed_header)
if multiple:
codeunit.SetCurrent(export.interface_file, export.Name())
export.GenerateCode(codeunit, exported_names)
# force collect of cyclic references
exports[i] = None
del declarations
del export
gc.collect()
# finally save the code unit
codeunit.Save()
print 'Module %s generated' % module
codeunit.Save()
if not multiple:
print 'Module %s generated' % module
return 0
def ExpandTypedefs(declarations, exported_names):
'''Check if the names in exported_names are a typedef, and add the real class
name in the dict.
'''
for name in exported_names.keys():
for decl in declarations:
if isinstance(decl, Typedef):
exported_names[decl.type.FullName()] = None
def UsePsyco():
'Tries to use psyco if possible'
try:

View File

@@ -0,0 +1,17 @@
#include <vector>
#include <string>
namespace abstract {
struct A {
virtual ~A() {}
virtual std::string f()=0;
};
struct B: A {
std::string f() { return "B::f"; }
};
std::string call(A* a) { return a->f(); }
}

View File

@@ -0,0 +1,3 @@
Class('abstract::A', 'abstract_test.h')
Class('abstract::B', 'abstract_test.h')
Function('abstract::call', 'abstract_test.h')

View File

@@ -0,0 +1,22 @@
import unittest
from _abstract_test import *
class AbstractTest(unittest.TestCase):
def testIt(self):
class C(A):
def f(self):
return 'C::f'
a = A()
b = B()
c = C()
self.assertRaises(RuntimeError, a.f)
self.assertEqual(b.f(), 'B::f')
self.assertEqual(call(b), 'B::f')
self.assertEqual(c.f(), 'C::f')
self.assertEqual(call(c), 'C::f')
if __name__ == '__main__':
unittest.main()

4
pyste/tests/code_test.h Normal file
View File

@@ -0,0 +1,4 @@
struct A {
int x;
};

View File

@@ -0,0 +1,9 @@
Class('A', 'code_test.h')
Include('string')
global_declaration_code('''
int get(A& a) { return a.x; }
std::string foo() { return "Hello!"; }
''')
module_code(' def("get", &get);\n')
module_code(' def("foo", &foo);\n')

View File

@@ -0,0 +1,14 @@
import unittest
from _code_test import *
class CodeTest(unittest.TestCase):
def testIt(self):
a = A()
a.x = 12
self.assertEqual(get(a), 12)
self.assertEqual(foo(), "Hello!")
if __name__ == '__main__':
unittest.main()

View File

@@ -4,12 +4,15 @@ struct A
{
int x;
int getx() { return x; }
int foo() { return 0; }
int foo(int x) { return x; }
};
struct B : A
{
int y;
int gety() { return y; }
int foo() { return 1; }
};
struct C : B

View File

@@ -1,3 +1,2 @@
header = AllFromHeader('inherit2.h')
exclude(header.A)
exclude(header.C)
Class('inherit2::B', 'inherit2.h')
Class('inherit2::D', 'inherit2.h')

View File

@@ -16,6 +16,8 @@ class InheritExampleTest(unittest.TestCase):
self.assertEqual(d.gety(), 15)
self.assertEqual(d.getz(), 10)
self.assertEqual(d.getw(), 5)
self.assertEqual(b.foo(), 1)
self.assertEqual(b.foo(3), 3)
def wrong():
return b.getw()

39
pyste/tests/inherit3.h Normal file
View File

@@ -0,0 +1,39 @@
namespace inherit3 {
struct A
{
struct X { int y; };
int x;
virtual int foo() { return 0; }
virtual int foo(int x) { return x; }
A operator+(A o) const
{
A r;
r.x = o.x + x;
return r;
}
enum E { i, j };
};
struct B: A
{
struct X { int y; };
int x;
int foo() { return 1; }
A operator+(A o) const
{
A r;
r.x = o.x + x;
return r;
}
enum E { i, j };
};
struct C: A
{
};
}

View File

@@ -0,0 +1,2 @@
Class('inherit3::B', 'inherit3.h')
Class('inherit3::C', 'inherit3.h')

23
pyste/tests/inherit3UT.py Normal file
View File

@@ -0,0 +1,23 @@
import unittest
from _inherit3 import *
class testInherit3(unittest.TestCase):
def testIt(self):
def testInst(c):
self.assertEqual(c.x, 0)
self.assertEqual(c.foo(3), 3)
x = c.X()
self.assertEqual(x.y, 0)
self.assertEqual(c.E.i, 0)
self.assertEqual(c.E.j, 1)
b = B()
c = C()
testInst(b)
testInst(c)
self.assertEqual(b.foo(), 1)
self.assertEqual(c.foo(), 0)
if __name__ == '__main__':
unittest.main()

View File

@@ -10,12 +10,12 @@ import sys
#=============================================================================
if sys.platform == 'win32':
includes = '-ID:/programming/libraries/boost-cvs/boost -IC:/Python/include'
build_pyste_cmd = 'python ../src/Pyste/pyste.py %s ' % includes
includes = '-ID:/programming/libraries/boost-cvs/boost -ID:/Bin/Python/include'
build_pyste_cmd = 'python ../src/Pyste/pyste.py --cache-dir=cache %s ' % includes
compile_single_cmd = 'icl /nologo /GR /GX -c %s -I. ' % includes
link_single_cmd = 'link /nologo /DLL '\
'/libpath:D:/programming/libraries/boost-cvs/lib /libpath:C:/Python/libs '\
'boost_python.lib python22.lib /out:_%s.dll '
'/libpath:D:/programming/libraries/boost-cvs/lib /libpath:D:/Bin/Python/libs '\
'boost_python.lib python23.lib /out:_%s.dll '
obj_ext = 'obj'
#=============================================================================
@@ -118,7 +118,7 @@ if __name__ == '__main__':
else:
module = None
try:
#main('--multiple', module)
# main('--multiple', module)
main('', module)
except RuntimeError, e:
print e