using libffi from rpython - a better way?

Hi All, First, let me say that PyPy just rocked my world. I develop an auto-update framework for frozen python applications [1] and have started using PyPy to compile parts of the app into stand-alone executables. I got it up and running in under two days, and it shaves several MB off the size of my frozen apps - so thanks for some awesome tech! I'm currently using libffi to dynamically find and load a python DLL from within an RPython program. It works well but the code seems very verbose to someone who's used to working with ctypes. I'm hoping there's a better way... Here's a trimmed-down example of the sort of thing I'm doing:: import ctypes.util libpython = ctypes.util.find_library("python2.6") from pypy.rlib.libffi import * from pypy.rpython.lltypesystem import rffi, lltype def target(*args): def entry_point(argv): # Find the python DLL and extract needed functions py = CDLL(libpython) Py_Initialize = py.getpointer("Py_Initialize",[],ffi_type_void) Py_Finalize = py.getpointer("Py_Finalize",[],ffi_type_void) PyRun_SimpleString = py.getpointer("PyRun_SimpleString",[ffi_type_pointer],ffi_type_sint) # Bootstrap into running a python program Py_Initialize.call(lltype.Void) buf = rffi.str2charp("print 'hello from python!'") PyRun_SimpleString.push_arg(buf) PyRun_SimpleString.call(rffi.INT) rffi.free_charp(buf) Py_Finalize.call(lltype.Void) return 0 return entry_point,None As you can imagine, the real application has a lot more of these boilerplate declarations. Any suggestions on how to do this in less/cleaner code? Thanks, Ryan [1] http://pypi.python.org/pypi/esky/ -- Ryan Kelly http://www.rfk.id.au | This message is digitally signed. Please visit ryan@rfk.id.au | http://www.rfk.id.au/ramblings/gpg/ for details

Hi, 2010/6/17 Ryan Kelly <ryan@rfk.id.au>:
# Find the python DLL and extract needed functions py = CDLL(libpython) Py_Initialize = py.getpointer("Py_Initialize",[],ffi_type_void) Py_Finalize = py.getpointer("Py_Finalize",[],ffi_type_void) PyRun_SimpleString = py.getpointer("PyRun_SimpleString",[ffi_type_pointer],ffi_type_sint)
As you can imagine, the real application has a lot more of these boilerplate declarations. Any suggestions on how to do this in less/cleaner code?
For the cpyext module, we used the documentation to generate stubs for every function of the API. It's easy to write a sphinx extension that processes every "cfunction" directive in the documentation. You could start with pypy/module/cpyext/stubgen.py and modify it for your needs, which are obviously different. It's poorly documented, but the comment for r72933 says: The stub generator works as follows: 1. Go to Doc (in your CPython checkout). 2. Run make text and stop it after it downloaded the prerequisites. 3. Apply the patch Doc_stubgen_enable.patch in your CPython checkout 4. Run make text again with PyPy in your Python path. 5. Voila, the stubs.py file will be updated. -- Amaury Forgeot d'Arc
participants (2)
-
Amaury Forgeot d'Arc
-
Ryan Kelly