[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

C function in a Python context

Aaron Brady

2/9/2008 7:49:00 PM

To write quick C things that Python won't do up to speed. So it's got
a redundancy.

import ext
extA= ext.Ext()
extA[ 'enumfactors' ]= r"""
int enumfactors( int a, const char* sep ) {
int ret= 0, i;
for( i= 1; i<= a; i++ ) {
if( a% i== 0 ) {
ret+= 1;
if( i> 1 ) {
printf( "%s", sep );
}
printf( "%i", i );
}
}
printf( "\n" );
return ret;
}
""", ("i","i","s")

factorsn= extA.enumfactors( 209677683, ', ' )
print( "%i factors total."% factorsn )

import sys
sys.exit()


1, 3, 23, 69, 131, 393, 3013, 9039, 23197, 69591, 533531, 1600593,
3038807, 9116
421, 69892561, 209677683
16 factors total.
3 Answers

Aaron Brady

2/9/2008 9:05:00 PM

0

On Feb 9, 1:48 pm, castiro...@gmail.com wrote:
> To write quick C things that Python won't do up to speed.  So it's got
> a redundancy.
>
> import ext
> extA= ext.Ext()
> extA[ 'enumfactors' ]= r"""
>     int enumfactors( int a, const char* sep ) {
>         int ret= 0, i;
>         for( i= 1; i<= a; i++ ) {
>             if( a% i== 0 ) {
>                 ret+= 1;
>                 if( i> 1 ) {
>                     printf( "%s", sep );
>                 }
>                 printf( "%i", i );
>             }
>         }
>         printf( "\n" );
>         return ret;
>     }
>     """, ("i","i","s")
>
> factorsn= extA.enumfactors( 209677683, ', ' )
> print( "%i factors total."% factorsn )
>
> import sys
> sys.exit()
>
> 1, 3, 23, 69, 131, 393, 3013, 9039, 23197, 69591, 533531, 1600593,
> 3038807, 9116
> 421, 69892561, 209677683
> 16 factors total.

'''Prototype implementation, slightly rigid. If anyone knows how to
compile and link without intermediate object file, and from a string,
memory, or stdin, let me know. Change first four lines. If you are
not using gcc, look at regenpyd().'''

compilercommand= 'c:/programs/mingw/bin/gcc'
pythondll= 'python30'
pythonpathinclude= 'c:/programs/python/include'
pythonpathlibs= 'c:/programs/python/libs'

class Ext:
strctypes= { 'i': 'int', 's': 'const char*' }
class ExtElem:
def __init__( self, name, code, types ):
self.name, self.code= name, code
self.types= types
def __init__( self ):
self.__dict__[ 'exts' ]= []
def regenc( self ):
extcode= open( 'extcode.c', 'w' )
wr= extcode.write
wr( '#include <%s'% pythonpathinclude )
wr( '/Python.h>\n\n' )
for ext in self.exts:
wr( ext.code )
wr( '\n' )
for ext in self.exts:
wr( 'static PyObject *\n' )
wr( 'extcode_%s'% ext.name )
wr( '(PyObject *self, ' )
wr( 'PyObject *args) {\n' )
wr( '\t%s result;\n'%
Ext.strctypes[ext.types[0]] )
for i, type in enumerate( ext.types[1:] ):
wr( '\t%s arg%i;\n'%
( Ext.strctypes[type], i ) )
wr( '\tPyArg_ParseTuple(args, "' )
wr( ''.join( ext.types[1:] ) )
wr( '"' )
for i, type in enumerate( ext.types[1:] ):
wr( ', &arg%i'% i )
wr( ' );\n' )
wr( '\tresult= %s( '% ext.name )
wr( ', '.join( [ 'arg%i'% i for i
in range( len( ext.types[1:] ) ) ] ) )
wr( ' );\n' )
wr( '\treturn Py_BuildValue' )
wr( '( "%s", result );\n'% ext.types[0] )
wr( '}\n\n' )
wr( 'static PyMethodDef ExtcodeMethods[] = {\n' )
for ext in self.exts:
wr( '\t{ "%s", extcode_%s, '%
( ext.name, ext.name ) )
wr( 'METH_VARARGS, "" },\n' )
wr( '\t{NULL, NULL, 0, NULL}\n' )
wr( '};\n\n' )
wr( 'PyMODINIT_FUNC\n' )
wr( 'initextcode(void) {\n' )
wr( '\t(void) Py_InitModule' )
wr( '("extcode", ExtcodeMethods);\n' )
wr( '}\n\n' )
extcode.close()
def regenpyd( self ):
import os, os.path
if os.path.exists( 'extcode.pyd' ):
os.remove( 'extcode.pyd' )
import subprocess
retcompile= subprocess.call(
'%s extcode.c -c -I%s'%
( compilercommand, pythonpathinclude ) )
assert not retcompile, 'Compiler error'
retlink= subprocess.call(
'%s -shared extcode.o -o extcode.pyd -L%s -l%s'
% ( compilercommand, pythonpathlibs,
pythondll ) )
assert not retlink, 'Linker error'
os.remove( 'extcode.o' )
os.remove( 'extcode.c' )
def __setitem__( self, key, value ):
code, types= value
self.exts.append( Ext.ExtElem( key, code, types ) )
self.regenc()
self.regenpyd()
import extcode
setattr( self, key, getattr( extcode, key ) )

Aaron Brady

2/12/2008 6:59:00 PM

0

On Feb 9, 3:04 pm, castiro...@gmail.com wrote:
> On Feb 9, 1:48 pm, castiro...@gmail.com wrote:
>
>
>
>
>
> > To write quick C things that Python won't do up to speed.  So it's got
> > a redundancy.
>
> > import ext
> > extA= ext.Ext()
> > extA[ 'enumfactors' ]= r"""
> >     int enumfactors( int a, const char* sep ) {
> >         int ret= 0, i;
> >         for( i= 1; i<= a; i++ ) {
> >             if( a% i== 0 ) {
> >                 ret+= 1;
> >                 if( i> 1 ) {
> >                     printf( "%s", sep );
> >                 }
> >                 printf( "%i", i );
> >             }
> >         }
> >         printf( "\n" );
> >         return ret;
> >     }
> >     """, ("i","i","s")
>
> > factorsn= extA.enumfactors( 209677683, ', ' )
> > print( "%i factors total."% factorsn )
>
> > import sys
> > sys.exit()
>
> > 1, 3, 23, 69, 131, 393, 3013, 9039, 23197, 69591, 533531, 1600593,
> > 3038807, 9116
> > 421, 69892561, 209677683
> > 16 factors total.
>
> '''Prototype implementation, slightly rigid.  If anyone knows how to
> compile and link without intermediate object file, and from a string,
> memory, or stdin, let me know.  Change first four lines.  If you are
> not using gcc, look at regenpyd().'''
>
> compilercommand=    'c:/programs/mingw/bin/gcc'
> pythondll=          'python30'
> pythonpathinclude=  'c:/programs/python/include'
> pythonpathlibs=     'c:/programs/python/libs'
>
> class Ext:
>     strctypes= { 'i': 'int', 's': 'const char*' }
>     class ExtElem:
>         def __init__( self, name, code, types ):
>             self.name, self.code= name, code
>             self.types= types
>     def __init__( self ):
>         self.__dict__[ 'exts' ]= []
>     def regenc( self ):
>         extcode= open( 'extcode.c', 'w' )
>         wr= extcode.write
>         wr( '#include <%s'% pythonpathinclude )
>         wr( '/Python.h>\n\n' )
>         for ext in self.exts:
>             wr( ext.code )
>             wr( '\n' )
>         for ext in self.exts:
>             wr( 'static PyObject *\n' )
>             wr( 'extcode_%s'% ext.name )
>             wr( '(PyObject *self, ' )
>             wr( 'PyObject *args) {\n' )
>             wr( '\t%s result;\n'%
>                 Ext.strctypes[ext.types[0]] )
>             for i, type in enumerate( ext.types[1:] ):
>                 wr( '\t%s arg%i;\n'%
>                     ( Ext.strctypes[type], i ) )
>             wr( '\tPyArg_ParseTuple(args, "' )
>             wr( ''.join( ext.types[1:] ) )
>             wr( '"' )
>             for i, type in enumerate( ext.types[1:] ):
>                 wr( ', &arg%i'% i )
>             wr( ' );\n' )
>             wr( '\tresult= %s( '% ext.name )
>             wr( ', '.join( [ 'arg%i'% i for i
>                 in range( len( ext.types[1:] ) ) ] ) )
>             wr( ' );\n' )
>             wr( '\treturn Py_BuildValue' )
>             wr( '( "%s", result );\n'% ext.types[0] )
>             wr( '}\n\n' )
>         wr( 'static PyMethodDef ExtcodeMethods[] = {\n' )
>         for ext in self.exts:
>             wr( '\t{ "%s", extcode_%s, '%
>                             ( ext.name, ext.name ) )
>             wr( 'METH_VARARGS, "" },\n' )
>         wr( '\t{NULL, NULL, 0, NULL}\n' )
>         wr( '};\n\n' )
>         wr( 'PyMODINIT_FUNC\n' )
>         wr( 'initextcode(void) {\n' )
>         wr( '\t(void) Py_InitModule' )
>         wr( '("extcode", ExtcodeMethods);\n' )
>         wr( '}\n\n' )
>         extcode.close()
>     def regenpyd( self ):
>         import os, os.path
>         if os.path.exists( 'extcode.pyd' ):
>             os.remove( 'extcode.pyd' )
>         import subprocess
>         retcompile= subprocess.call(
>             '%s extcode.c -c -I%s'%
>             ( compilercommand, pythonpathinclude ) )
>         assert not retcompile, 'Compiler error'
>         retlink= subprocess.call(
>             '%s -shared extcode.o -o extcode.pyd -L%s -l%s'
>             % ( compilercommand, pythonpathlibs,
>             pythondll ) )
>         assert not retlink, 'Linker error'
>         os.remove( 'extcode.o' )
>         os.remove( 'extcode.c' )
>     def __setitem__( self, key, value ):
>         code, types= value
>         self.exts.append( Ext.ExtElem( key, code, types ) )
>         self.regenc()
>         self.regenpyd()
>         import extcode
>         setattr( self, key, getattr( extcode, key ) )- Hide quoted text -
>
> - Show quoted text -

This is- and returns a list, of the enumerated factors. Is it
starting to get bulky.


import ext
extA= ext.Ext()
extA[ 'enumfactors' ]= r"""
#include <string>
#include <vector>
using namespace std;
PyObject* enumfactors( int a, const char* sep ) {
string fmt= "[";
vector< long > resv;
for( int i= 1; i<= a; i++ ) {
if( a% i== 0 ) {
resv.push_back( i );
fmt.append( "i" );
if( i> 1 ) {
printf( "%s", sep );
}
printf( "%i", i );
}
}
printf( "\n" );
fmt.append( "]" );
PyObject* res= PyList_New( resv.size() );
for( int i= 0; i< resv.size(); i++ ) {
PyObject* v= PyLong_FromLong( resv[i] );
int succ= PyList_SetItem( res, i, v );
}
return res;
}
""", ("O","i","s")


factorsn= extA.enumfactors( 209677683, ', ' )
print( factorsn )


Aaron Brady

2/19/2008 9:09:00 PM

0

> #include <string>
> #include <vector>

This modification required:

compilercommand= 'c:/programs/mingw/bin/g++'

and

strctypes= { 'i': 'int', 's': 'const char*',
'O': 'PyObject*' }

The output is:

#include <c:/programs/python/include/Python.h>

[ user code ]

static PyObject *
extcode_enumfactors(PyObject *self, PyObject *args) {
PyObject* result;
int arg0;
const char* arg1;
PyArg_ParseTuple(args, "is", &arg0, &arg1 );
result= enumfactors( arg0, arg1 );
return Py_BuildValue( "O", result );
}

static PyMethodDef ExtcodeMethods[] = {
{ "enumfactors", extcode_enumfactors, METH_VARARGS, "" },
{NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initextcode(void) {
(void) Py_InitModule("extcode", ExtcodeMethods);
}

The benefits are automatic parameter parsing and automatic method
table construction. The costs are portability and parameter parsing
flexibility. Add up.