[pygccxml-commit] SF.net SVN: pygccxml:[1386] pyplusplus_dev
Brought to you by:
mbaas,
roman_yakovenko
|
From: <rom...@us...> - 2008-08-08 12:18:11
|
Revision: 1386
http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1386&view=rev
Author: roman_yakovenko
Date: 2008-08-08 12:18:18 +0000 (Fri, 08 Aug 2008)
Log Message:
-----------
adding new features: exposing anonymous structs and anonymous unions, exposing variables, that has union as a type
Modified Paths:
--------------
pyplusplus_dev/docs/documentation/www_configuration.py
pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py
pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py
pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py
pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py
pyplusplus_dev/pyplusplus/messages/warnings_.py
pyplusplus_dev/pyplusplus/module_builder/builder.py
pyplusplus_dev/pyplusplus/module_creator/creator.py
pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py
pyplusplus_dev/unittests/data/unnamed_classes_to_be_exported.hpp
pyplusplus_dev/unittests/module_body_tester.py
pyplusplus_dev/unittests/unnamed_classes_tester.py
Added Paths:
-----------
pyplusplus_dev/docs/documentation/ctypes/
pyplusplus_dev/unittests/data/unions_to_be_exported.hpp
pyplusplus_dev/unittests/unions_tester.py
Removed Paths:
-------------
pyplusplus_dev/docs/documentation/ctypes_integration.rest
Deleted: pyplusplus_dev/docs/documentation/ctypes_integration.rest
===================================================================
--- pyplusplus_dev/docs/documentation/ctypes_integration.rest 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/docs/documentation/ctypes_integration.rest 2008-08-08 12:18:18 UTC (rev 1386)
@@ -1,148 +0,0 @@
-==================
-ctypes integration
-==================
-
-.. contents:: Table of contents
-
-------------
-Introduction
-------------
-
-`Boost.Python`_ is really a very powerful library, but if you are working
-with code written in plain "C" - you've got a problem. You have to create
-wrappers for almost every function or variable.
-
-In general, if you want to work with plain "C" code from `Python`_
-you don't have to create any wrapper - you can use `ctypes`_ package.
-
-About ctypes
-------------
-`ctypes`_ is a foreign function library for Python. It provides C
-compatible data types, and allows to call functions in dlls/shared
-libraries. It can be used to wrap these libraries in pure Python.
-
-
-
-The idea behind "ctypes integration" functionality is simple: you
-configure `Py++`_ to expose address of the variables or return
-values, as integer and than you can use `ctypes`_ `from_address`_
-functionality to access the data.
-
-Obviously, this approach has its price:
-
-* it could be very dangerous - you can corrupt your application memory
-
-* managing memory is not something a typical `Python`_ user get used to.
- It is too "low level".
-
-In my opinion, the better way to go is to "mix":
-
-1. expose your native code using `Boost.Python`_ and "ctypes integration"
- functionality
-
-2. use `ctypes`_ module to access your data
-
-3. create high level API: the wrappers, which will ensure the constraints
- and will provide more "natural" interface
-
---------------
-Usage examples
---------------
-
-Variables
----------
-
-Lets say you have the following C++ code:
-
- .. code-block:: C++
-
- struct bytes_t{
- bytes_t(){
- data = new int[5];
- for(int i=0; i<5; i++){
- data[i] = i;
- }
- }
- ...
- int* data;
- static int* x;
- };
-
- //somewhere in a cpp file
- int* bytes_t::x = new int( 1997 );
-
-In order to get access to the ``bytes_t::data`` and ``bytes_t::x`` you
-have to turn on ``expose_address`` property to ``True``:
-
- .. code-block:: Python
-
- mb = module_builder_t( ... )
- bytes = mb.class_( 'bytes_t' )
- bytes.vars().expose_address = True
-
-`Py++`_ will generate code, which will expose the address of the variables.
-
-and now it is a time to show some `ctypes`_ magic:
-
- .. code-block:: Python
-
- import ctypes
- import your_module as m
-
- bytes = m.bytes_t()
-
- data_type = ctypes.POINTER( ctypes.c_int )
- data = data_type.from_address( bytes.data )
- for j in range(5):
- print '%d : %d' % ( j, data[j] )
-
- data_type = ctypes.POINTER( ctypes.c_int )
- data = data_type.from_address( m.bytes_t.x )
- print x.contents.value
-
-
-"this" pointer
---------------
-
-`Py++`_ can expose "this" pointer value to `Python`_:
-
- .. code-block:: Python
-
- mb = module_builder_t( ... )
- mb.class_( 'bytes_t' ).expose_this = True
-
-and the usage example:
-
- .. code-block:: Python
-
- import ctypes
- import your_module as m
-
- print m.bytes_t().this
-
-
-Warning: I hope you know what you are doing, otherwise don't blame me :-)
-
------------------
-Future directions
------------------
-
-The functionality is going to be developed father and I intend to add
-next features:
-
-* to expose the result of "sizeof" applied on a class or variable
-
-* to add new call policy, which will return value of a pointer as integer
-
-* to port this functionality to 64bit systems
-
-* to add support for unions
-
-.. _`ctypes` : http://docs.python.org/lib/module-ctypes.html
-.. _`from_address` : http://docs.python.org/lib/ctypes-data-types.html
-.. _`Py++` : ./../pyplusplus.html
-.. _`pygccxml` : ./../../pygccxml/pygccxml.html
-.. _`Boost.Python`: http://www.boost.org/libs/python/doc/index.html
-.. _`Python`: http://www.python.org
-.. _`GCC-XML`: http://www.gccxml.org
-
Modified: pyplusplus_dev/docs/documentation/www_configuration.py
===================================================================
--- pyplusplus_dev/docs/documentation/www_configuration.py 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/docs/documentation/www_configuration.py 2008-08-08 12:18:18 UTC (rev 1386)
@@ -8,5 +8,4 @@
, 'best_practices' : 'best practices'
, 'multi_module_development' : 'multi-module development'
, 'split_module' : 'splitting generated code to files'
- , 'ctypes_integration' : 'ctypes integration'
}
Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py
===================================================================
--- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2008-08-08 12:18:18 UTC (rev 1386)
@@ -54,7 +54,7 @@
def _get_create_with_signature(self):
if None is self._create_with_signature:
self._create_with_signature = bool( self.overloads )
-
+
if not self._create_with_signature and declarations.templates.is_instantiation( self.name ):
self._create_with_signature = True
@@ -73,7 +73,7 @@
self._create_with_signature \
= bool( self.parent.calldefs( self.name, recursive=False, allow_empty=True ) )
return self._create_with_signature
-
+
def _set_create_with_signature(self, create_with_signature):
self._create_with_signature = create_with_signature
create_with_signature = property( _get_create_with_signature, _set_create_with_signature
@@ -159,6 +159,8 @@
return ''
def _exportable_impl( self ):
+ if not self.parent.name:
+ return messages.W1057 % str( self )
all_types = [ arg.type for arg in self.arguments ]
all_types.append( self.return_type )
for some_type in all_types:
@@ -398,7 +400,7 @@
included = filter( lambda decl: decl.ignore == False, oper.class_types )
if not included:
return messages.W1052 % str(oper)
-
+
return ''
class member_operator_t( declarations.member_operator_t, calldef_t ):
Modified: pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py
===================================================================
--- pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2008-08-08 12:18:18 UTC (rev 1386)
@@ -370,10 +370,16 @@
def _exportable_impl( self ):
if not self.name:
- return messages.W1018
- #it is possible to do so, but not for unnamed classes defined under namespace.
+ named_parent = declarations.get_named_parent( self )
+ if not named_parent:
+ return messages.W1057 % str( self )
+ if isinstance( named_parent, declarations.namespace_t ):
+ return messages.W1018 % str( self )
if self.class_type == declarations.CLASS_TYPES.UNION:
- return messages.W1054
+ if self.is_wrapper_needed():
+ return messages.W1059 % str( self )
+ if self.name:
+ return messages.W1060 % str( self )
if isinstance( self.parent, declarations.namespace_t ):
return ''
if not self in self.parent.public_members:
@@ -587,14 +593,7 @@
if isinstance( member, declarations.destructor_t ):
continue
if isinstance( member, declarations.variable_t ):
- if member.bits:
- explanation.append( messages.W1024 % member.name )
- if declarations.is_pointer( member.type ):
- explanation.append( messages.W1025 % member.name )
- if declarations.is_reference( member.type ):
- explanation.append( messages.W1026 % member.name )
- if declarations.is_array( member.type ):
- explanation.append( messages.W1027 % member.name)
+ explanation.extend( member.is_wrapper_needed() )
if isinstance( member, declarations.class_t ) and member.is_wrapper_needed():
explanation.append( messages.W1028 % member.name)
if isinstance( member, declarations.calldef_t ):
@@ -636,3 +635,16 @@
self._expose_this = new_value
expose_this = property( _get_expose_this, _set_expose_this
, doc="boolean, if True an object address( this pointer ) will be exposed to Python as integer.")
+
+ @property
+ def introduces_new_scope(self):
+ """returns True, if during exposing this class, new scope will be created
+
+ For example, anonymous structs will be exposed in a parent scope.
+ """
+ if not self.name:
+ return False
+ elif self.class_type == declarations.CLASS_TYPES.UNION:
+ return False
+ else:
+ return True
Modified: pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py
===================================================================
--- pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py 2008-08-08 12:18:18 UTC (rev 1386)
@@ -75,3 +75,8 @@
if len( set( name2value.keys() ) ) != len( set( name2value.values() ) ):
msgs.append( messages.W1032 )
return msgs
+
+ def _exportable_impl( self ):
+ if not self.parent.name:
+ return messages.W1057 % str( self )
+ return ''
Modified: pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py
===================================================================
--- pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py 2008-08-08 12:18:18 UTC (rev 1386)
@@ -23,7 +23,8 @@
self._is_read_only = None
self._use_make_functions = None
self._expose_address = None
-
+ self._expose_value = None
+
__call_policies_doc__ = \
"""There are usecase, when exporting member variable forces Py++ to
create accessors functions. Sometime, those functions requires call policies.
@@ -56,7 +57,7 @@
def get_setter_call_policies( self ):
if None is self._getter_call_policies:
if self.apply_smart_ptr_wa or self.use_make_functions:
- self._setter_call_policies = call_policies.default_call_policies()
+ self._setter_call_policies = call_policies.default_call_policies()
return self._setter_call_policies
def set_setter_call_policies( self, call_policies ):
self._setter_call_policies = call_policies
@@ -65,15 +66,15 @@
__use_make_functions_doc__ = \
"""Generate code using make_getter and make_setter functions
-
+
Basically you don't need to use this, untill you have one of the next use-cases:
* member variable is smart pointer - in this case Boost.Python has small problem
to expose it right. Using the functions is a work around to the problem.
* member variable defined custom r-value converter - may be you don't know
- but the conversion is applied only on functions arguments. So you need to
+ but the conversion is applied only on functions arguments. So you need to
use make_getter/make_setter in order to allow user to enjoy from the
conversion.
-
+
Setting "apply_smart_ptr_wa" and/or "use_make_functions" to "True" will tell
Py++ to generate such code.
"""
@@ -92,32 +93,64 @@
use_make_functions = property( get_use_make_functions, set_use_make_functions
, doc=__use_make_functions_doc__)
+ def __should_be_exposed_by_address_only(self):
+ type_ = declarations.remove_alias( self.type )
+ type_ = declarations.remove_const( type_ )
+ type_ = declarations.remove_pointer( type_ )
+ if not declarations.class_traits.is_my_case( type_ ):
+ return False
+ cls = declarations.class_traits.get_declaration( type_ )
+ if cls.class_type == declarations.CLASS_TYPES.UNION:
+ return True
+ elif not cls.name:
+ return True
+ else:
+ return False
+
__expose_address_doc__ = \
"""There are some cases when Boost.Python doesn't provide a convenient way
to expose the variable to Python. For example:
-
+
double* x[10];
//or
char* buffer; //in case you want to modify the buffer in place
-
- In this cases Py++ doesn't help too. In these cases it is possible to expose
+
+ In this cases Py++ doesn't help too. In these cases it is possible to expose
the actual address of the variable. After that, you can use built-in "ctypes"
- package to edit the content of the variable.
+ package to edit the content of the variable.
"""
def get_expose_address( self ):
+ if None is self._expose_address:
+ self._expose_address = self.__should_be_exposed_by_address_only()
return self._expose_address
def set_expose_address( self, value ):
self._expose_address = value
expose_address = property( get_expose_address, set_expose_address
, doc= __expose_address_doc__ )
-
+ __expose_value_doc__ = \
+ """Boost.Python is not able to expose unions. Using ctypes module
+ it is possible to get access to the data stored in a variable, which
+ has some union type.
+
+ This property controls whether Py++ should expose the variable value
+ or not. In case, this variable has type union, this property will be False.
+ """
+ def get_expose_value( self ):
+ if None is self._expose_value:
+ self._expose_value = not self.__should_be_exposed_by_address_only()
+ return self._expose_value
+ def set_expose_value( self, value ):
+ self._expose_value = value
+ expose_value = property( get_expose_value, set_expose_value
+ , doc= __expose_value_doc__ )
+
def __find_out_is_read_only(self):
type_ = declarations.remove_alias( self.type )
-
+
if isinstance( type_, declarations.const_t ):
return True
-
+
if declarations.is_pointer( type_ ):
type_ = declarations.remove_pointer( type_ )
@@ -126,16 +159,16 @@
if isinstance( type_, declarations.const_t ):
return True
-
+
if self.apply_smart_ptr_wa:
return False #all smart pointers has assign operator
-
+
if isinstance( type_, declarations.declarated_t ) \
and isinstance( type_.declaration, declarations.class_t ) \
and not declarations.has_public_assign( type_.declaration ):
return True
return False
-
+
def get_is_read_only( self ):
if None is self._is_read_only:
self._is_read_only = self.__find_out_is_read_only()
@@ -145,8 +178,9 @@
is_read_only = property( get_is_read_only, set_is_read_only )
def _exportable_impl( self ):
- if self.name == 'f':
- i = 0
+ if not self.parent.name and self.is_wrapper_needed():
+ #return messages.W1057 % str( self )
+ return messages.W1058 % str( self )
if not self.name:
return messages.W1033
if self.bits == 0 and self.name == "":
@@ -172,6 +206,8 @@
cls = declarations.class_traits.get_declaration( type_ )
if not cls.name:
return messages.W1038
+ #if cls.class_type == declarations.CLASS_TYPES.UNION:
+ # return messages.W1061 % ( str( self ), str( cls ) )
if isinstance( self.parent, declarations.class_t ):
if self.access_type != declarations.ACCESS_TYPES.PUBLIC:
return messages.W1039
@@ -182,3 +218,19 @@
if python_traits.is_immutable( item_type_no_ptr ):
return messages.W1056
return ''
+
+ def is_wrapper_needed(self):
+ """returns an explanation( list of str ) why wrapper is needed.
+
+ If wrapper is not needed than [] will be returned.
+ """
+ explanation = []
+ if self.bits:
+ explanation.append( messages.W1024 % self.name )
+ if declarations.is_pointer( self.type ):
+ explanation.append( messages.W1025 % self.name )
+ if declarations.is_reference( self.type ):
+ explanation.append( messages.W1026 % self.name )
+ if declarations.is_array( self.type ):
+ explanation.append( messages.W1027 % self.name)
+ return explanation
Modified: pyplusplus_dev/pyplusplus/messages/warnings_.py
===================================================================
--- pyplusplus_dev/pyplusplus/messages/warnings_.py 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/pyplusplus/messages/warnings_.py 2008-08-08 12:18:18 UTC (rev 1386)
@@ -99,11 +99,11 @@
W1016 = warning(
'Py++ does not exports non-const casting operators with user defined type as return value. '
- 'This could be change in future.' )
+ 'This could be changed in future.' )
W1017 = compilation_error( "Py++ doesn't export non-public casting operators." )
-W1018 = compilation_error( 'Py++ can not expose unnamed classes.' )
+W1018 = compilation_error( 'Py++ can not expose anonymous class "%s", declared in a namespace.' )
W1019 = compilation_error( 'Py++ can not expose private class.' )
@@ -139,7 +139,7 @@
"http://boost.org/libs/python/todo.html#support-for-enums-with-duplicate-values . "
"The quick work around is to add new class variable to the exported enum, from Python. " )
-W1033 = compilation_error( "Py++ can not expose unnamed variables" )
+W1033 = compilation_error( "Py++ can not expose anonymous variables" )
W1034 = compilation_error( "Py++ can not expose alignment bit." )
@@ -151,7 +151,7 @@
"Boost.Python library can not expose variables, which are pointer to function."
" See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information." )
-W1038 = compilation_error( "Py++ can not expose variables of with unnamed type." )
+W1038 = compilation_error( "Py++ can not expose variables of with anonymous type." )
W1039 = compilation_error( "Py++ doesn't expose private or protected member variables." )
@@ -222,6 +222,21 @@
W1056 = compilation_error( "Py++ can not expose array of pointers of Python immutable types. Take a look on 'ctypes integration' feature." )
+W1057 = compilation_error( 'Py++ can not expose "%s" - it does not belong to named class.' )
+
+W1058 = compilation_error( 'Py++ can not expose "%s" it belongs to anonymous class'
+ ' and requires additional code to expose.'
+ ' This could be changed in future.')
+
+W1059 = compilation_error( 'Py++ can not expose "%s" - it requires additional code to expose.'
+ ' This could be changed in future.')
+
+W1060 = compilation_error( 'Py++ can not expose "%s" - it has name, Py++ only exposes anonymous unions.'
+ ' This could be changed in future.')
+
+W1061 = compilation_error( 'Py++ can not expose "%s" - its type is "%s".'
+ ' This could be changed in future.')
+
warnings = globals()
all_warning_msgs = []
Modified: pyplusplus_dev/pyplusplus/module_builder/builder.py
===================================================================
--- pyplusplus_dev/pyplusplus/module_builder/builder.py 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/pyplusplus/module_builder/builder.py 2008-08-08 12:18:18 UTC (rev 1386)
@@ -6,7 +6,7 @@
import os
import sys
import time
-
+import types
import warnings
from pygccxml import parser
@@ -97,7 +97,7 @@
self.__registrations_code_head = []
self.__registrations_code_tail = []
-
+
@property
def global_ns( self ):
"""reference to global namespace"""
@@ -108,19 +108,19 @@
return self.__encoding
def register_module_dependency( self, other_module_generated_code_dir ):
- """``already_exposed`` solution is pretty good when you mix hand-written
- modules with Py++ generated. It doesn't work/scale for "true"
- multi-module development. This is exactly the reason why ``Py++``_
+ """``already_exposed`` solution is pretty good when you mix hand-written
+ modules with Py++ generated. It doesn't work/scale for "true"
+ multi-module development. This is exactly the reason why ``Py++``_
offers "semi automatic" solution.
- For every exposed module, ``Py++``_ generates "exposed_decl.pypp.txt" file.
- This file contains the list of all parsed declarations and whether they
- were included or excluded. Later, when you work on another module, you
- can tell ``Py++``_ that the current module depends on the previously
- generated one. ``Py++``_ will load "exposed_decl.pypp.txt" file and
+ For every exposed module, ``Py++``_ generates "exposed_decl.pypp.txt" file.
+ This file contains the list of all parsed declarations and whether they
+ were included or excluded. Later, when you work on another module, you
+ can tell ``Py++``_ that the current module depends on the previously
+ generated one. ``Py++``_ will load "exposed_decl.pypp.txt" file and
update the declarations.
"""
-
+
db = utils.exposed_decls_db_t()
db.load( other_module_generated_code_dir )
db.update_decls( self.global_ns )
@@ -305,6 +305,23 @@
else:
self.__registrations_code_head.append( code )
+ def add_constants( self, **keywds ):
+ """adds code that exposes some constants to Python.
+
+ For example:
+ mb.add_constants( version='"1.2.3"' )
+ or
+ mb.add_constants( **{ version:'"1.2.3"' } )
+ will generate next code:
+ boost::python::scope().attr("version") = "1.2.3";
+ """
+ tmpl = 'boost::python::scope().attr("%(name)s") = %(value)s;'
+ for name, value in keywds.items():
+ if not isinstance( value, types.StringTypes ):
+ value = str( value )
+ self.add_registration_code( tmpl % dict( name=name, value=value) )
+
+
def __merge_user_code( self ):
for code in self.__declarations_code_tail:
self.code_creator.add_declaration_code( code, -1 )
@@ -365,24 +382,24 @@
This could speed-up code generation process by 10-15%.
"""
self.__merge_user_code()
-
- files_sum_repository = None
+
+ files_sum_repository = None
if use_files_sum_repository:
cache_file = os.path.join( dir_name, self.code_creator.body.name + '.md5.sum' )
files_sum_repository = file_writers.cached_repository_t( cache_file )
-
+
written_files = []
if None is huge_classes:
- written_files = file_writers.write_multiple_files(
+ written_files = file_writers.write_multiple_files(
self.code_creator
, dir_name
, files_sum_repository=files_sum_repository
, encoding=self.encoding)
else:
- written_files = file_writers.write_class_multiple_files(
+ written_files = file_writers.write_class_multiple_files(
self.code_creator
, dir_name
- , huge_classes
+ , huge_classes
, files_sum_repository=files_sum_repository
, encoding=self.encoding)
self.__work_on_unused_files( dir_name, written_files, on_unused_file_found )
@@ -411,18 +428,18 @@
This could speed-up code generation process by 10-15%.
"""
self.__merge_user_code()
-
- files_sum_repository = None
+
+ files_sum_repository = None
if use_files_sum_repository:
cache_file = os.path.join( dir_name, self.code_creator.body.name + '.md5.sum' )
files_sum_repository = file_writers.cached_repository_t( cache_file )
-
+
written_files = file_writers.write_balanced_files( self.code_creator
, dir_name
, number_of_buckets=number_of_files
, files_sum_repository=files_sum_repository
, encoding=self.encoding)
-
+
self.__work_on_unused_files( dir_name, written_files, on_unused_file_found )
return written_files
@@ -470,7 +487,7 @@
, header_file=header_file
, recursive=recursive)
var = variable
-
+
def variables( self, name=None, function=None, type=None, header_dir=None, header_file=None, recursive=None ):
"""Please see L{decl_wrappers.scopedef_t} class documentation"""
return self.global_ns.variables( name=name
@@ -480,7 +497,7 @@
, header_file=header_file
, recursive=recursive)
vars = variables
-
+
def calldef( self, name=None, function=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None ):
"""Please see L{decl_wrappers.scopedef_t} class documentation"""
return self.global_ns.calldef( name=name
@@ -651,7 +668,7 @@
, header_file=header_file
, recursive=recursive )
free_fun = free_function
-
+
def free_functions( self, name=None, function=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None ):
"""Please see L{decl_wrappers.namespace_t} class documentation"""
return self.global_ns.free_functions( name=name
@@ -662,7 +679,7 @@
, header_file=header_file
, recursive=recursive)
free_funs = free_functions
-
+
def free_operator( self, name=None, function=None, symbol=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None ):
"""Please see L{decl_wrappers.namespace_t} class documentation"""
return self.global_ns.free_operator( name=name
Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py
===================================================================
--- pyplusplus_dev/pyplusplus/module_creator/creator.py 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2008-08-08 12:18:18 UTC (rev 1386)
@@ -19,16 +19,6 @@
ACCESS_TYPES = declarations.ACCESS_TYPES
VIRTUALITY_TYPES = declarations.VIRTUALITY_TYPES
-#TODO: add print decl_wrapper.readme messages
-#class Foo{
-# union {
-# struct {
-# float r,g,b,a;
-# };
-# float val[4];
-# };
-# };
-
class creator_t( declarations.decl_visitor_t ):
"""Creating code creators.
@@ -561,7 +551,11 @@
exportable_members = self.curr_decl.get_exportable_members(sort_algorithms.sort)
wrapper = None
- cls_cc = code_creators.class_t( class_inst=self.curr_decl )
+ cls_cc = None
+ if cls_decl.introduces_new_scope:
+ cls_cc = code_creators.class_t( class_inst=self.curr_decl )
+ else:
+ cls_cc = self.curr_code_creator
if self.curr_decl.is_wrapper_needed():
wrapper = code_creators.class_wrapper_t( declaration=self.curr_decl
@@ -591,7 +585,8 @@
exposed = self.expose_overloaded_mem_fun_using_macro( cls_decl, cls_cc )
- cls_parent_cc.adopt_creator( cls_cc )
+ if cls_decl.introduces_new_scope:
+ cls_parent_cc.adopt_creator( cls_cc )
self.curr_code_creator = cls_cc
if cls_decl.expose_this:
@@ -672,6 +667,9 @@
self.curr_code_creator.adopt_creator( creator_type(self.curr_decl) )
return
+ if not self.curr_decl.expose_value:
+ return
+
if declarations.is_array( self.curr_decl.type ):
if self._register_array_1( self.curr_decl.type ):
array_1_registrator = code_creators.array_1_registrator_t( array_type=self.curr_decl.type )
Modified: pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py
===================================================================
--- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2008-08-08 12:18:18 UTC (rev 1386)
@@ -6,7 +6,7 @@
"""defines class, which informs user about used, but unexposed declarations"""
import os
-from pyplusplus import utils
+from pyplusplus import utils
from pyplusplus import messages
from pygccxml import declarations
from pyplusplus import decl_wrappers
@@ -17,19 +17,19 @@
object.__init__( self )
self.__exported_decls = []
self.__logger = logger
-
+
def add_exported( self, decl ):
- self.__exported_decls.append( decl )
+ self.__exported_decls.append( decl )
def __select_duplicate_aliases( self, decls ):
duplicated = {}
for decl in decls:
if not duplicated.has_key( decl.alias ):
duplicated[ decl.alias ] = set()
- duplicated[ decl.alias ].add( decl )
+ duplicated[ decl.alias ].add( decl )
for alias, buggy_decls in duplicated.items():
if 1 == len( buggy_decls ):
- del duplicated[ alias ]
+ del duplicated[ alias ]
return duplicated
def __report_duplicate_aliases_impl( self, control_decl, duplicated ):
@@ -39,7 +39,7 @@
warning = messages.W1047 % ( control_decl.alias
, os.linesep.join( map( str, buggy_decls ) ) )
self.__logger.warn( "%s;%s" % ( control_decl, warning ) )
-
+
if isinstance( control_decl, declarations.class_t ):
query = lambda i_decl: isinstance( i_decl, declarations.class_types ) \
and i_decl.ignore == False
@@ -55,7 +55,7 @@
duplicated = self.__select_duplicate_aliases( decls )
for decl in decls:
self.__report_duplicate_aliases_impl( decl, duplicated )
-
+
def __is_std_decl( self, decl ):
#Every class under std should be exported by Boost.Python and\\or Py++
#Also this is not the case right now, I prefer to hide the warnings
@@ -80,7 +80,7 @@
dependencies = filter( lambda d: d.access_type != declarations.ACCESS_TYPES.PRIVATE
, dependencies )
return dependencies
-
+
def __find_out_used_but_not_exported( self ):
used_not_exported = []
exported_ids = set( map( lambda d: id( d ), self.__exported_decls ) )
@@ -97,10 +97,13 @@
if isinstance( depend_on_decl, declarations.class_types ):
if depend_on_decl.opaque:
continue
+ if isinstance( decl, declarations.variable_t ):
+ if not decl.expose_value:
+ continue
if id( depend_on_decl ) not in exported_ids:
report = messages.filter_disabled_msgs([messages.W1040], depend_on_decl.disabled_messaged )
if report:
- used_not_exported.append( dependency )
+ used_not_exported.append( dependency )
return used_not_exported
def __group_by_unexposed( self, dependencies ):
@@ -118,7 +121,7 @@
for dependency in dependencies:
decls.append( os.linesep + ' ' + str( dependency.declaration ) )
return "%s;%s" % ( depend_on_decl, messages.W1040 % ''.join( decls ) )
-
+
def inform_user( self ):
used_not_exported_decls = self.__find_out_used_but_not_exported()
groups = self.__group_by_unexposed( used_not_exported_decls )
Added: pyplusplus_dev/unittests/data/unions_to_be_exported.hpp
===================================================================
--- pyplusplus_dev/unittests/data/unions_to_be_exported.hpp (rev 0)
+++ pyplusplus_dev/unittests/data/unions_to_be_exported.hpp 2008-08-08 12:18:18 UTC (rev 1386)
@@ -0,0 +1,35 @@
+namespace unions{
+
+struct data_t{
+ union actual_data_t{
+ int i;
+ double d;
+ };
+ actual_data_t data;
+
+ double get_d() const{ return data.d; }
+ int get_i() const{ return data.i; }
+
+ void set_d( double d ){ data.d = d; }
+ void set_i( int i ){ data.i = i; }
+};
+
+}
+
+namespace anonymous_unions{
+
+struct data2_t{
+ union{
+ int i;
+ double d;
+ };
+
+ double get_d() const{ return d; }
+ int get_i() const{ return i; }
+
+ void set_d( double _d ){ d = _d; }
+ void set_i( int _i ){ i = _i; }
+
+};
+
+}
Modified: pyplusplus_dev/unittests/data/unnamed_classes_to_be_exported.hpp
===================================================================
--- pyplusplus_dev/unittests/data/unnamed_classes_to_be_exported.hpp 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/unittests/data/unnamed_classes_to_be_exported.hpp 2008-08-08 12:18:18 UTC (rev 1386)
@@ -6,21 +6,21 @@
#ifndef __unnamed_enums_to_be_exported_hpp__
#define __unnamed_enums_to_be_exported_hpp__
-namespace unnamed_enums{
-
-class color{
- union{
- struct {
- float r,g,b,a;
- };
- float val[4];
- };
-};
-
-struct{
- int x;
-} unnamed_struct_with_mem_var_x;
+namespace unnamed_enums{
+struct color{
+ union{
+ struct {
+ float r,g,b,a;
+ };
+ float val[4];
+ };
+};
+
+struct{
+ int x;
+} unnamed_struct_with_mem_var_x;
+
}
#endif//__unnamed_enums_to_be_exported_hpp__
Modified: pyplusplus_dev/unittests/module_body_tester.py
===================================================================
--- pyplusplus_dev/unittests/module_body_tester.py 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/unittests/module_body_tester.py 2008-08-08 12:18:18 UTC (rev 1386)
@@ -10,14 +10,14 @@
class tester_t(fundamental_tester_base.fundamental_tester_base_t):
EXTENSION_NAME = 'module_body'
-
+
def __init__( self, *args ):
- fundamental_tester_base.fundamental_tester_base_t.__init__(
+ fundamental_tester_base.fundamental_tester_base_t.__init__(
self
, tester_t.EXTENSION_NAME
, *args )
- def customize(self, mb):
+ def customize(self, mb):
item = mb.class_( 'item_t' )
item.include()
item.add_declaration_code( "int get11( const mb::item_t& item ){ return 11;}" )
@@ -31,12 +31,14 @@
mb.build_code_creator( self.EXTENSION_NAME )
- def run_tests(self, module):
+ mb.add_constants( version='"0.0.0"')
+
+ def run_tests(self, module):
self.failUnless( 1 == module.get1() )
self.failUnless( 11 == module.item_t().get11() )
-
+ self.failUnless( "0.0.0" == module.version )
def create_suite():
- suite = unittest.TestSuite()
+ suite = unittest.TestSuite()
suite.addTest( unittest.makeSuite(tester_t))
return suite
@@ -44,4 +46,4 @@
unittest.TextTestRunner(verbosity=2).run( create_suite() )
if __name__ == "__main__":
- run_suite()
\ No newline at end of file
+ run_suite()
Added: pyplusplus_dev/unittests/unions_tester.py
===================================================================
--- pyplusplus_dev/unittests/unions_tester.py (rev 0)
+++ pyplusplus_dev/unittests/unions_tester.py 2008-08-08 12:18:18 UTC (rev 1386)
@@ -0,0 +1,53 @@
+# Copyright 2004 Roman Yakovenko.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import os
+import sys
+import ctypes
+import unittest
+import fundamental_tester_base
+
+class actual_data_t( ctypes.Union ):
+ _fields_ = [( "i", ctypes.c_int ), ( 'd', ctypes.c_double )]
+
+#this is compilation test
+class tester_t(fundamental_tester_base.fundamental_tester_base_t):
+ EXTENSION_NAME = 'unions'
+
+ def __init__( self, *args ):
+ fundamental_tester_base.fundamental_tester_base_t.__init__(
+ self
+ , tester_t.EXTENSION_NAME
+ , *args )
+
+ def run_tests(self, module):
+ obj = module.data_t()
+ actual_data = actual_data_t.from_address( obj.data )
+ obj.set_d( 4.0 )
+ self.failUnless( actual_data.d == 4.0 )
+ obj.set_i( 1977 )
+ self.failUnless( actual_data.i == 1977 )
+ actual_data.i = 18
+ self.failUnless( obj.get_i() == 18 )
+ actual_data.d = 12.12
+ self.failUnless( obj.get_d() == 12.12 )
+
+ obj2 = module.data2_t()
+ obj2.set_d( 4.0 )
+ self.failUnless( obj2.d == 4.0 )
+ obj2.set_i( 1977 )
+ self.failUnless( obj2.i == 1977 )
+
+
+def create_suite():
+ suite = unittest.TestSuite()
+ suite.addTest( unittest.makeSuite(tester_t))
+ return suite
+
+def run_suite():
+ unittest.TextTestRunner(verbosity=2).run( create_suite() )
+
+if __name__ == "__main__":
+ run_suite()
Modified: pyplusplus_dev/unittests/unnamed_classes_tester.py
===================================================================
--- pyplusplus_dev/unittests/unnamed_classes_tester.py 2008-08-08 10:51:47 UTC (rev 1385)
+++ pyplusplus_dev/unittests/unnamed_classes_tester.py 2008-08-08 12:18:18 UTC (rev 1386)
@@ -7,22 +7,24 @@
import sys
import unittest
import fundamental_tester_base
-from pyplusplus import code_creators
+from pygccxml import declarations
+from pyplusplus import code_creators
class unnamed_enums_tester_t(fundamental_tester_base.fundamental_tester_base_t):
EXTENSION_NAME = 'unnamed_classes'
-
+
def __init__( self, *args ):
- fundamental_tester_base.fundamental_tester_base_t.__init__(
+ fundamental_tester_base.fundamental_tester_base_t.__init__(
self
, unnamed_enums_tester_t.EXTENSION_NAME
, *args )
- def run_tests(self, module):
- pass
-
+ def run_tests(self, module):
+ color = module.color()
+ r,g,b,a = color.r, color.g, color.b, color.a
+
def create_suite():
- suite = unittest.TestSuite()
+ suite = unittest.TestSuite()
suite.addTest( unittest.makeSuite(unnamed_enums_tester_t))
return suite
@@ -30,4 +32,4 @@
unittest.TextTestRunner(verbosity=2).run( create_suite() )
if __name__ == "__main__":
- run_suite()
\ No newline at end of file
+ run_suite()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|