Hi all, I have a problem with GcStruct, Struct and Ptr I can not resolve with my own devices. After some trial with ctypes running on CPython I came up with the following lowlevel representation for structures: Ptr( GcStruct( "CtypesGcStructure_<ClassName> ( "c_data" (Struct "C-Data_<ClassName> *<Fieldefintions>) ) ) ) Samuele and Armin helped to implement rtype_getattr and rtype_setattr that delegate all attribute access to the c_data field, by pointing out how to implement a helper method called generateCDataAccess: def generateCDataAccess( self, variable, lowLevelOperations ): """ Answer the C level data sub structure. """ inputargs = [ variable, inputconst( Void, "c_data" ) ] return lowLevelOperations.genop( "getfield", inputargs, # Using Ptr makes the C-compiler barf, # omitting Ptr leeds to specialisation errors Ptr( self.c_data_lowleveltype ) ) def rtype_setattr( self, highLevelOperation ): c_data = self.generateCDataAccess( highLevelOperation.inputarg( self, 0 ), highLevelOperation.llops ) inputargs = highLevelOperation.inputargs( *highLevelOperation.args_r[ :3 ] ) inputargs[ 0 ] = c_data print "inputargs:", inputargs print "r_result:", highLevelOperation.r_result highLevelOperation.genop( "setfield", inputargs ) Obviously generateCDataAccess needs to return a Ptr to the embedded C-structure. When I use Ptr as in the example above, I get the following traceback: c:\Dokumente und Einstellungen\root\Lokale Einstellungen\Temp\usession-353\testi ng_2\testing_2.c(894) : error C2440: '=': 'pypy_C_Data_tagpoint0' kann nicht in 'pypy_C_Data_tagpoint0 *' konvertiert werden Which means, that a 'pypy_C_Data_tagpoint0' can not be converted to a 'pypy_C_Data_tagpoint0 *'. A brief look at the generated C-source, shows that the compiler is right here: struct pypy_CtypesStructure_tagpoint0 *pypy_g__py_test_compile_struct(struct pypy_CtypesStructure_tagpoint0 *l_p_0, long l_x_1, long l_y_1) { /*void l_v111;*/ /*void l_v112;*/ struct pypy_C_Data_tagpoint0 *l_v98; struct pypy_C_Data_tagpoint0 *l_v99; struct pypy_CtypesStructure_tagpoint0 *l_v110; pypy_IncRf_CtypesStructure_tagpoint0(l_p_0); block0: l_v98 = l_p_0->cs_c_data; l_v98->cd_x = l_x_1; l_v99 = l_p_0->cs_c_data; l_v99->cd_y = l_y_1; l_v110 = l_p_0; goto block1; block1: return l_v110; } If I ommit the Ptr construction so that, generateCDataAccess is defined as follows: def generateCDataAccess( self, variable, lowLevelOperations ): """ Answer the C level data sub structure. """ inputargs = [ variable, inputconst( Void, "c_data" ) ] return lowLevelOperations.genop( "getfield", inputargs, self.c_data_lowleveltype ) I get the following error: [D:\svnwork\work\dist\pypy\rpython\lltypesystem\lltype.py:146] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _nofield(self, name): raise AttributeError, 'struct %s has no field %r' % (self._name, E name) > AttributeError: struct C-Data_tagpoint has no field 'TO' This is no surprise at all. The getfield operation obviosly needs a pointer to work with. So it boils down to the question: How can I access the members of an embedded structure? Is there a possibility to get the address of substructure, just like C's ampersand (&) operator does? Any help is welcome. Best regards, Gerald
Gerald Klix wrote:
Hi all, I have a problem with GcStruct, Struct and Ptr I can not resolve with my own devices.
After some trial with ctypes running on CPython I came up with the following lowlevel representation for structures:
Ptr( GcStruct( "CtypesGcStructure_<ClassName> ( "c_data" (Struct "C-Data_<ClassName> *<Fieldefintions>) ) ) )
to access c_data from a pointer to the surrounding GcStruct, you want the operation "getsubstruct", not "gefield" which is only for Primitive and pointer fields (not substructures), getsubstruct will return a pointer correctly. The low level operations for access are together: getfield / setfield getsubstruct (there's no setsubstruct) getarrayitem / setarrayitem getarraysubstruct (for array of structs) getarraysize and we have a cast_pointer also
Samuele and Armin helped to implement rtype_getattr and rtype_setattr that delegate all attribute access to the c_data field, by pointing out how to implement a helper method called generateCDataAccess:
def generateCDataAccess( self, variable, lowLevelOperations ): """ Answer the C level data sub structure. """ inputargs = [ variable, inputconst( Void, "c_data" ) ] return lowLevelOperations.genop( "getfield", inputargs, # Using Ptr makes the C-compiler barf, # omitting Ptr leeds to specialisation errors Ptr( self.c_data_lowleveltype ) )
def rtype_setattr( self, highLevelOperation ): c_data = self.generateCDataAccess( highLevelOperation.inputarg( self, 0 ), highLevelOperation.llops ) inputargs = highLevelOperation.inputargs( *highLevelOperation.args_r[ :3 ] ) inputargs[ 0 ] = c_data print "inputargs:", inputargs print "r_result:", highLevelOperation.r_result highLevelOperation.genop( "setfield", inputargs )
Obviously generateCDataAccess needs to return a Ptr to the embedded C-structure. When I use Ptr as in the example above, I get the following traceback:
c:\Dokumente und Einstellungen\root\Lokale Einstellungen\Temp\usession-353\testi ng_2\testing_2.c(894) : error C2440: '=': 'pypy_C_Data_tagpoint0' kann nicht in 'pypy_C_Data_tagpoint0 *' konvertiert werden
Which means, that a 'pypy_C_Data_tagpoint0' can not be converted to a 'pypy_C_Data_tagpoint0 *'. A brief look at the generated C-source, shows that the compiler is right here:
struct pypy_CtypesStructure_tagpoint0 *pypy_g__py_test_compile_struct(struct pypy_CtypesStructure_tagpoint0 *l_p_0, long l_x_1, long l_y_1) { /*void l_v111;*/ /*void l_v112;*/ struct pypy_C_Data_tagpoint0 *l_v98; struct pypy_C_Data_tagpoint0 *l_v99; struct pypy_CtypesStructure_tagpoint0 *l_v110; pypy_IncRf_CtypesStructure_tagpoint0(l_p_0);
block0: l_v98 = l_p_0->cs_c_data; l_v98->cd_x = l_x_1; l_v99 = l_p_0->cs_c_data; l_v99->cd_y = l_y_1; l_v110 = l_p_0; goto block1;
block1: return l_v110; }
If I ommit the Ptr construction so that, generateCDataAccess is defined as follows:
def generateCDataAccess( self, variable, lowLevelOperations ): """ Answer the C level data sub structure. """ inputargs = [ variable, inputconst( Void, "c_data" ) ] return lowLevelOperations.genop( "getfield", inputargs, self.c_data_lowleveltype )
I get the following error:
[D:\svnwork\work\dist\pypy\rpython\lltypesystem\lltype.py:146] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
def _nofield(self, name): raise AttributeError, 'struct %s has no field %r' % (self._name, E name) > AttributeError: struct C-Data_tagpoint has no field 'TO'
This is no surprise at all. The getfield operation obviosly needs a pointer to work with.
So it boils down to the question: How can I access the members of an embedded structure? Is there a possibility to get the address of substructure, just like C's ampersand (&) operator does?
Any help is welcome.
Best regards, Gerald
_______________________________________________ pypy-dev@codespeak.net http://codespeak.net/mailman/listinfo/pypy-dev
participants (2)
-
Gerald Klix -
Samuele Pedroni