Revision: 1479
http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1479&view=rev
Author: roman_yakovenko
Date: 2008-12-20 19:23:18 +0000 (Sat, 20 Dec 2008)
Log Message:
-----------
making the test work again.
Changes: no cyclic references, the lookup in dll is done only once.
Modified Paths:
--------------
pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.cpp
pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.h
pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.suo
pyplusplus_dev/pyplusplus/cpptypes/mydll/release/mydll.dll
pyplusplus_dev/pyplusplus/cpptypes/tester.py
Added Paths:
-----------
pyplusplus_dev/pyplusplus/cpptypes/name_mapping.py
Modified: pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.cpp
===================================================================
--- pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.cpp 2008-12-19 22:50:32 UTC (rev 1478)
+++ pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.cpp 2008-12-20 19:23:18 UTC (rev 1479)
@@ -34,6 +34,10 @@
return number_t(*this);
}
+std::auto_ptr<number_t> number_t::clone_ptr() const{
+ return std::auto_ptr<number_t>( new number_t( *this ) );
+}
+
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
Modified: pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.h
===================================================================
--- pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.h 2008-12-19 22:50:32 UTC (rev 1478)
+++ pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.h 2008-12-20 19:23:18 UTC (rev 1479)
@@ -1,5 +1,7 @@
#pragma once
+#include <memory>
+
class __declspec(dllexport) number_t{
public:
number_t();
@@ -10,8 +12,9 @@
void set_value(int x);
number_t clone() const;
-
+ std::auto_ptr<number_t> clone_ptr() const;
private:
int m_value;
};
+template class __declspec(dllexport) std::auto_ptr< number_t >;
Modified: pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.suo
===================================================================
(Binary files differ)
Modified: pyplusplus_dev/pyplusplus/cpptypes/mydll/release/mydll.dll
===================================================================
(Binary files differ)
Added: pyplusplus_dev/pyplusplus/cpptypes/name_mapping.py
===================================================================
--- pyplusplus_dev/pyplusplus/cpptypes/name_mapping.py (rev 0)
+++ pyplusplus_dev/pyplusplus/cpptypes/name_mapping.py 2008-12-20 19:23:18 UTC (rev 1479)
@@ -0,0 +1,94 @@
+"""
+The "data" dictionary was generate dusing the following code:
+
+
+import pprint
+from pygccxml.msvc import mspdb
+from pygccxml import declarations
+from pygccxml.msvc import common_utils as msvc_utils
+
+pdb_file = r'E:\development\language-binding\pyplusplus_dev\pyplusplus\cpptypes\mydll\release\mydll.pdb'
+
+reader = mspdb.decl_loader_t( pdb_file )
+opt = mspdb.enums.UNDECORATE_NAME_OPTIONS.UNDNAME_SCOPES_ONLY
+
+d = {}
+for smbl in reader.public_symbols.itervalues():
+ name = smbl.name
+ undecorated_name = smbl.get_undecoratedNameEx(opt)
+ d[ name ] = undecorated_name
+ d[ undecorated_name ] = name
+
+pprint.pprint( d )
+
+
+Obviously the result is too big and some additional work should be done.
+"""
+
+data = \
+{u'??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z': u'std::basic_ostream<char,std::char_traits<char> > & std::operator<<<std::char_traits<char> >(std::basic_ostream<char,std::char_traits<char> > &,char const *)',
+ u'??0?$auto_ptr@Vnumber_t@@@std@@QAE@AAV01@@Z': u'std::auto_ptr<number_t>::auto_ptr<number_t>(std::auto_ptr<number_t> &)',
+ u'??0?$auto_ptr@Vnumber_t@@@std@@QAE@PAVnumber_t@@@Z': u'std::auto_ptr<number_t>::auto_ptr<number_t>(number_t *)',
+ u'??0?$auto_ptr@Vnumber_t@@@std@@QAE@U?$auto_ptr_ref@Vnumber_t@@@1@@Z': u'std::auto_ptr<number_t>::auto_ptr<number_t>(std::auto_ptr_ref<number_t>)',
+ u'??0number_t@@QAE@ABV0@@Z': u'number_t::number_t(number_t const &)',
+ u'??0number_t@@QAE@H@Z': u'number_t::number_t(int)',
+ u'??0number_t@@QAE@XZ': u'number_t::number_t(void)',
+ u'??0sentry@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAE@AAV12@@Z': u'std::basic_ostream<char,std::char_traits<char> >::sentry::sentry(std::basic_ostream<char,std::char_traits<char> > &)',
+ u'??1?$auto_ptr@Vnumber_t@@@std@@QAE@XZ': u'std::auto_ptr<number_t>::~auto_ptr<number_t>(void)',
+ u'??1_Sentry_base@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAE@XZ': u'std::basic_ostream<char,std::char_traits<char> >::_Sentry_base::~_Sentry_base(void)',
+ u'??1number_t@@UAE@XZ': u'number_t::~number_t(void)',
+ u'??1sentry@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAE@XZ': u'std::basic_ostream<char,std::char_traits<char> >::sentry::~sentry(void)',
+ u'??2@YAPAXI@Z': u'void * operator new(unsigned int)',
+ u'??3@YAXPAX@Z': u'void operator delete(void *)',
+ u'??4?$auto_ptr@Vnumber_t@@@std@@QAEAAV01@AAV01@@Z': u'std::auto_ptr<number_t> & std::auto_ptr<number_t>::operator=(std::auto_ptr<number_t> &)',
+ u'??4?$auto_ptr@Vnumber_t@@@std@@QAEAAV01@U?$auto_ptr_ref@Vnumber_t@@@1@@Z': u'std::auto_ptr<number_t> & std::auto_ptr<number_t>::operator=(std::auto_ptr_ref<number_t>)',
+ u'??4number_t@@QAEAAV0@ABV0@@Z': u'number_t & number_t::operator=(number_t const &)',
+ u'??C?$auto_ptr@Vnumber_t@@@std@@QBEPAVnumber_t@@XZ': u'number_t * std::auto_ptr<number_t>::operator->(void)',
+ u'??D?$auto_ptr@Vnumber_t@@@std@@QBEAAVnumber_t@@XZ': u'number_t & std::auto_ptr<number_t>::operator*(void)',
+ u'??_Enumber_t@@UAEPAXI@Z': u"void * number_t::`vector deleting destructor'(unsigned int)",
+ u'??_F?$auto_ptr@Vnumber_t@@@std@@QAEXXZ': u"void std::auto_ptr<number_t>::`default constructor closure'(void)",
+ u'??_M@YGXPAXIHP6EX0@Z@Z': u"void `eh vector destructor iterator'(void *,unsigned int,int,void (*)(void *))",
+ u'??_V@YAXPAX@Z': u'void operator delete[](void *)',
+ u'?clone@number_t@@QBE?AV1@XZ': u'number_t number_t::clone(void)',
+ u'?clone_ptr@number_t@@QBE?AV?$auto_ptr@Vnumber_t@@@std@@XZ': u'std::auto_ptr<number_t> number_t::clone_ptr(void)',
+ u'?get@?$auto_ptr@Vnumber_t@@@std@@QBEPAVnumber_t@@XZ': u'number_t * std::auto_ptr<number_t>::get(void)',
+ u'?get_value@number_t@@QBEHXZ': u'int number_t::get_value(void)',
+ u'?print_it@number_t@@QBEXXZ': u'void number_t::print_it(void)',
+ u'?release@?$auto_ptr@Vnumber_t@@@std@@QAEPAVnumber_t@@XZ': u'number_t * std::auto_ptr<number_t>::release(void)',
+ u'?reset@?$auto_ptr@Vnumber_t@@@std@@QAEXPAVnumber_t@@@Z': u'void std::auto_ptr<number_t>::reset(number_t *)',
+ u'?set_value@number_t@@QAEXH@Z': u'void number_t::set_value(int)',
+ u'?terminate@@YAXXZ': u'void terminate(void)',
+ u'_DllMain@12': u'_DllMain@12',
+ u'_atexit': u'_atexit',
+ u'int number_t::get_value(void)': u'?get_value@number_t@@QBEHXZ',
+ u'number_t & number_t::operator=(number_t const &)': u'??4number_t@@QAEAAV0@ABV0@@Z',
+ u'number_t & std::auto_ptr<number_t>::operator*(void)': u'??D?$auto_ptr@Vnumber_t@@@std@@QBEAAVnumber_t@@XZ',
+ u'number_t * std::auto_ptr<number_t>::get(void)': u'?get@?$auto_ptr@Vnumber_t@@@std@@QBEPAVnumber_t@@XZ',
+ u'number_t * std::auto_ptr<number_t>::operator->(void)': u'??C?$auto_ptr@Vnumber_t@@@std@@QBEPAVnumber_t@@XZ',
+ u'number_t * std::auto_ptr<number_t>::release(void)': u'?release@?$auto_ptr@Vnumber_t@@@std@@QAEPAVnumber_t@@XZ',
+ u'number_t number_t::clone(void)': u'?clone@number_t@@QBE?AV1@XZ',
+ u'number_t::number_t(int)': u'??0number_t@@QAE@H@Z',
+ u'number_t::number_t(number_t const &)': u'??0number_t@@QAE@ABV0@@Z',
+ u'number_t::number_t(void)': u'??0number_t@@QAE@XZ',
+ u'number_t::~number_t(void)': u'??1number_t@@UAE@XZ',
+ u'std::auto_ptr<number_t> & std::auto_ptr<number_t>::operator=(std::auto_ptr<number_t> &)': u'??4?$auto_ptr@Vnumber_t@@@std@@QAEAAV01@AAV01@@Z',
+ u'std::auto_ptr<number_t> & std::auto_ptr<number_t>::operator=(std::auto_ptr_ref<number_t>)': u'??4?$auto_ptr@Vnumber_t@@@std@@QAEAAV01@U?$auto_ptr_ref@Vnumber_t@@@1@@Z',
+ u'std::auto_ptr<number_t> number_t::clone_ptr(void)': u'?clone_ptr@number_t@@QBE?AV?$auto_ptr@Vnumber_t@@@std@@XZ',
+ u'std::auto_ptr<number_t>::auto_ptr<number_t>(number_t *)': u'??0?$auto_ptr@Vnumber_t@@@std@@QAE@PAVnumber_t@@@Z',
+ u'std::auto_ptr<number_t>::auto_ptr<number_t>(std::auto_ptr<number_t> &)': u'??0?$auto_ptr@Vnumber_t@@@std@@QAE@AAV01@@Z',
+ u'std::auto_ptr<number_t>::auto_ptr<number_t>(std::auto_ptr_ref<number_t>)': u'??0?$auto_ptr@Vnumber_t@@@std@@QAE@U?$auto_ptr_ref@Vnumber_t@@@1@@Z',
+ u'std::auto_ptr<number_t>::~auto_ptr<number_t>(void)': u'??1?$auto_ptr@Vnumber_t@@@std@@QAE@XZ',
+ u'std::basic_ostream<char,std::char_traits<char> > & std::operator<<<std::char_traits<char> >(std::basic_ostream<char,std::char_traits<char> > &,char const *)': u'??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z',
+ u'std::basic_ostream<char,std::char_traits<char> >::_Sentry_base::~_Sentry_base(void)': u'??1_Sentry_base@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAE@XZ',
+ u'std::basic_ostream<char,std::char_traits<char> >::sentry::sentry(std::basic_ostream<char,std::char_traits<char> > &)': u'??0sentry@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAE@AAV12@@Z',
+ u'std::basic_ostream<char,std::char_traits<char> >::sentry::~sentry(void)': u'??1sentry@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAE@XZ',
+ u"void * number_t::`vector deleting destructor'(unsigned int)": u'??_Enumber_t@@UAEPAXI@Z',
+ u'void * operator new(unsigned int)': u'??2@YAPAXI@Z',
+ u"void `eh vector destructor iterator'(void *,unsigned int,int,void (*)(void *))": u'??_M@YGXPAXIHP6EX0@Z@Z',
+ u'void number_t::print_it(void)': u'?print_it@number_t@@QBEXXZ',
+ u'void number_t::set_value(int)': u'?set_value@number_t@@QAEXH@Z',
+ u'void operator delete(void *)': u'??3@YAXPAX@Z',
+ u'void operator delete[](void *)': u'??_V@YAXPAX@Z',
+ u"void std::auto_ptr<number_t>::`default constructor closure'(void)": u'??_F?$auto_ptr@Vnumber_t@@@std@@QAEXXZ',
+ u'void std::auto_ptr<number_t>::reset(number_t *)': u'?reset@?$auto_ptr@Vnumber_t@@@std@@QAEXPAVnumber_t@@@Z',
+ u'void terminate(void)': u'?terminate@@YAXXZ'}
Modified: pyplusplus_dev/pyplusplus/cpptypes/tester.py
===================================================================
--- pyplusplus_dev/pyplusplus/cpptypes/tester.py 2008-12-19 22:50:32 UTC (rev 1478)
+++ pyplusplus_dev/pyplusplus/cpptypes/tester.py 2008-12-20 19:23:18 UTC (rev 1479)
@@ -1,7 +1,6 @@
import ctypes
import unittest
-import decorators
-
+import name_mapping
mydll = ctypes.CPPDLL( './mydll/release/mydll.dll' )
#we should keep somewhere decorated-undecorated name mappings
@@ -11,71 +10,87 @@
# GCCXML reports mangled and demangled names of the function, but it is not a cross platform( compile ) solution.
# It looks like I will have to cause mspdb package to work ( from where ctypes loads dlls? ctypes.windll.msvcr90 ???
+mydll.name_mapping = name_mapping.data
-tmp = [ ( "number_t::number_t(class number_t const &)", "??0number_t@@QAE@ABV0@@Z" )
- , ( "number_t::number_t(int)", "??0number_t@@QAE@H@Z" )
- , ( "number_t::number_t(void)", "??0number_t@@QAE@XZ" )
- , ( "number_t::~number_t(void)", "??1number_t@@UAE@XZ" )
- , ( "class number_t & number_t::operator=(class number_t const &)", "??4number_t@@QAEAAV0@ABV0@@Z" )
- , ( "const number_t::'vftable'", "??_7number_t@@6B@" )
- , ( "int number_t::get_value(void)", "?get_value@number_t@@QBEHXZ" )
- , ( "void number_t::print_it(void)", "?print_it@number_t@@QBEXXZ" )
- , ( "void number_t::set_value(int)", "?set_value@number_t@@QAEXH@Z" ) ]
-
-mydll.name_mapping = {}
-for n1, n2 in tmp:
- mydll.name_mapping[n1] = n2
- mydll.name_mapping[n2] = n1
-
# what is the best way to treat overloaded constructors
class public( object ):
- def __init__(self, dll, this, name, restype=None, argtypes=None ):
- self.this = this #reference to class instance
+ def __init__(self, dll, name, restype=None, argtypes=None ):
self.name = name
self.func = getattr( dll, dll.name_mapping[name] )
self.func.restype = restype
- this_call_arg_types = [ ctypes.POINTER( this._obj.__class__ ) ]
- if argtypes:
- this_call_arg_types.extend( argtypes )
- self.func.argtypes = this_call_arg_types
+ self.func.argtypes = argtypes
def __call__(self, *args, **keywd ):
- return self.func( self.this, *args, **keywd )
+ return self.func( *args, **keywd )
class mem_fun_factory( object ):
- def __init__( self, dll, this ):
+ def __init__( self, dll, class_ ):
self.dll = dll
- self.this = this
+ self.this_type = ctypes.POINTER( class_ )
- def __call__( self, *args, **keywd ):
- return public( self.dll, self.this, *args, **keywd )
+ def __call__( self, name, **keywd ):
+ if 'argtypes' not in keywd:
+ keywd['argtypes'] = [ self.this_type ]
+ else:
+ keywd['argtypes'].insert( 0, self.this_type )
+ return public( self.dll, name, **keywd )
+
class Number(ctypes.Structure):
#http://www.phpcompiler.org/articles/virtualinheritance.html,
_fields_ = [("vptr", ctypes.POINTER(ctypes.c_void_p)),
("m_value", ctypes.c_int)]
+ _methods_ = {}
+
def __init__(self, x=None):
- mem_fun = mem_fun_factory( mydll, ctypes.byref( self ) )
- self.get_value = mem_fun( 'int number_t::get_value(void)', restype=ctypes.c_int )
- self.set_value = mem_fun( 'void number_t::set_value(int)', argtypes=[ctypes.c_int])
- self.print_it = mem_fun( 'void number_t::print_it(void)' )
- self.assign = mem_fun( "class number_t & number_t::operator=(class number_t const &)"
- , restype=ctypes.POINTER(Number)
- , argtypes=[ctypes.POINTER(Number)] )
+ self.__this = ctypes.byref( self )
#overloading example
if None is x:
- mem_fun( 'number_t::number_t(void)' )()
+ self._methods_['default_constructor']( self.__this )
elif isinstance( x, int ):
- mem_fun( 'number_t::number_t(int)', argtypes=[ctypes.c_int] )( x )
+ self._methods_['from_int_constructor']( self.__this, x )
elif isinstance( x, Number ):
- mem_fun( 'number_t::number_t(class number_t const &)', argtypes=[ctypes.POINTER(Number)] )( ctypes.byref( x ) )
+ self._methods_['copy_constructor']( self.__this, ctypes.byref( x ) )
else:
raise RuntimeError( "Wrong argument" )
+ def get_value( self, *args, **keywd ):
+ return self._methods_['get_value']( self.__this, *args, **keywd )
+
+ def set_value( self, *args, **keywd ):
+ return self._methods_['set_value']( self.__this, *args, **keywd )
+
+ def print_it( self, *args, **keywd ):
+ return self._methods_['print_it']( self.__this, *args, **keywd )
+
+ def assign( self, *args, **keywd ):
+ return self._methods_['assign']( self.__this, *args, **keywd )
+
def __del__(self):
- public( mydll, ctypes.byref(self), "number_t::~number_t(void)" )()
+ self._methods_['destructor']( self.__this )
+
+mem_fun = mem_fun_factory( mydll, Number )
+Number._methods_ = {
+ #constructors
+ 'default_constructor' : mem_fun( 'number_t::number_t(void)' )
+ , 'from_int_constructor' : mem_fun( 'number_t::number_t(int)', argtypes=[ctypes.c_int] )
+ , 'copy_constructor' : mem_fun( 'number_t::number_t(number_t const &)', argtypes=[ctypes.POINTER(Number)] )
+ #member functions
+ , 'get_value' : mem_fun( 'int number_t::get_value(void)', restype=ctypes.c_int )
+ , 'set_value' : mem_fun( 'void number_t::set_value(int)', argtypes=[ctypes.c_int])
+ , 'print_it' : mem_fun( 'void number_t::print_it(void)' )
+ #operator=
+ , 'assign' : mem_fun( "number_t & number_t::operator=(number_t const &)"
+ , restype=ctypes.POINTER(Number)
+ , argtypes=[ctypes.POINTER(Number)] )
+ #destructor
+ , 'destructor' : mem_fun( 'number_t::~number_t(void)' )
+}
+del mem_fun
+
+
class tester_t( unittest.TestCase ):
def test_constructors(self):
obj1 = Number(32)
@@ -129,5 +144,12 @@
class X{...};
class Y{ X x; public: const X& get_x() const { return x;} };
I think our solution should be very similar to Boost.Python call policies. It is definitely possible to go without it.
+* template classes:
+ in the following use case, the members of std:auto_ptr class are not exported
+ class number_t{...};
+ std::auto_ptr<number_t> do_smth();
+ The user will have to change the code to add
+ template class __declspec(dllexport) std::auto_ptr< number_t >;
+ and recompile
"""
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|