C function in a Python context
castironpi at gmail.com
castironpi at gmail.com
Tue Feb 12 13:58:36 EST 2008
On Feb 9, 3:04 pm, castiro... at gmail.com wrote:
> On Feb 9, 1:48 pm, castiro... at 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 )
More information about the Python-list
mailing list