[pypy-svn] r26043 - in pypy/dist/pypy/translator/llvm/wrapable: . test
ericvrp at codespeak.net
ericvrp at codespeak.net
Thu Apr 20 16:18:07 CEST 2006
Author: ericvrp
Date: Thu Apr 20 16:17:39 2006
New Revision: 26043
Added:
pypy/dist/pypy/translator/llvm/wrapable/
pypy/dist/pypy/translator/llvm/wrapable/__init__.py (contents, props changed)
pypy/dist/pypy/translator/llvm/wrapable/libllvm.cpp
pypy/dist/pypy/translator/llvm/wrapable/libllvm.h
pypy/dist/pypy/translator/llvm/wrapable/llvm.py (contents, props changed)
pypy/dist/pypy/translator/llvm/wrapable/llvm_helper.py (contents, props changed)
pypy/dist/pypy/translator/llvm/wrapable/setup.py (contents, props changed)
pypy/dist/pypy/translator/llvm/wrapable/test/
pypy/dist/pypy/translator/llvm/wrapable/test/test_llvm.py (contents, props changed)
pypy/dist/pypy/translator/llvm/wrapable/wrap_llvm.py (contents, props changed)
pypy/dist/pypy/translator/llvm/wrapable/wrapable.py (contents, props changed)
pypy/dist/pypy/translator/llvm/wrapable/wrapper.py (contents, props changed)
Log:
Code I have been working on for to long without staying in contact with the
other PyPy developers.
It's purpose is to use C++ libraries with (r)ctypes.
The code will generate .h, .cpp and .py files out of a class specification.
This specs look similar to boost.Python . From my experience with prior
project I know that C++ header files with all it's inline function, templates,
etc. quickly become to complicated to handle automaticly. Even with a tool such
as gccxml there are often no clear cut solutions. That is the why.
As an example you can look at wrap_llvm.py , which when executed creates libllvm.h
libllvm.cpp (the C API) and llvm.py (the Python classes which mimic the C++ API's
behaviour)
A pointer to the original C++ object is stored in the 'instance' attribute of the
Python class. Whenever one of these Python objects is used as a parameter ctypes
automatically uses the objects 'instance' attribute instead. (see wrapper.py from_param)
I am no sure if we (can) support this in rctypes as well, otherwise this tool could
do it for us.
I hope this code can be of use and that I did not isolate me too much for too long!
Added: pypy/dist/pypy/translator/llvm/wrapable/__init__.py
==============================================================================
Added: pypy/dist/pypy/translator/llvm/wrapable/libllvm.cpp
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/wrapable/libllvm.cpp Thu Apr 20 16:17:39 2006
@@ -0,0 +1,116 @@
+// llvm.cpp
+
+#include "libllvm.h"
+
+// Helper functions (mostly for casting returnvalues and parameters)
+char* as_c_string(std::string str) {
+ return (char*)str.c_str();
+}
+
+std::string as_std_string(char* p) {
+ return std::string(p);
+}
+
+std::vector<GenericValue> as_vector_GenericValue(GenericValue* gv) {
+ std::vector<GenericValue> gvv;
+ gvv.push_back(*gv);
+ return gvv;
+}
+
+// ExecutionEngine
+ExecutionEngine* ExecutionEngine_create(ModuleProvider* P0,long P1) {
+ return (ExecutionEngine*)ExecutionEngine::create(P0,P1);
+}
+
+Module& ExecutionEngine_getModule(ExecutionEngine* P0) {
+ return (Module&)P0->getModule();
+}
+
+void ExecutionEngine_freeMachineCodeForFunction(ExecutionEngine* P0,Function* P1) {
+ return (void)P0->freeMachineCodeForFunction(P1);
+}
+
+GenericValue ExecutionEngine_runFunction(ExecutionEngine* P0,Function* P1,GenericValue* P2) {
+ return (GenericValue)P0->runFunction(P1,as_vector_GenericValue(P2));
+}
+
+
+// ModuleProvider
+
+// ExistingModuleProvider
+ExistingModuleProvider* ExistingModuleProvider___init__(Module* P0) {
+ return new ExistingModuleProvider(P0);
+}
+
+
+// Function
+void Function_eraseFromParent(Function* P0) {
+ return (void)P0->eraseFromParent();
+}
+
+FunctionType* Function_getFunctionType(Function* P0) {
+ return (FunctionType*)P0->getFunctionType();
+}
+
+
+// FunctionType
+
+// GenericValue
+
+// TypeID
+
+// Type
+TypeID* Type_getTypeID(Type* P0) {
+ return (TypeID*)P0->getTypeID();
+}
+
+Type* Type_getContainedType(Type* P0,long P1) {
+ return (Type*)P0->getContainedType(P1);
+}
+
+char* Type_getDescription(Type* P0) {
+ return (char*)as_c_string(P0->getDescription());
+}
+
+
+// Module
+Module* Module___init__(char* P0) {
+ return new Module(as_std_string(P0));
+}
+
+char* Module_getModuleIdentifier(Module* P0) {
+ return (char*)as_c_string(P0->getModuleIdentifier());
+}
+
+void Module_setModuleIdentifier(Module* P0,char* P1) {
+ return (void)P0->setModuleIdentifier(P1);
+}
+
+char* Module_getTargetTriple(Module* P0) {
+ return (char*)as_c_string(P0->getTargetTriple());
+}
+
+void Module_setTargetTriple(Module* P0,char* P1) {
+ return (void)P0->setTargetTriple(P1);
+}
+
+char* Module_getModuleInlineAsm(Module* P0) {
+ return (char*)as_c_string(P0->getModuleInlineAsm());
+}
+
+void Module_setModuleInlineAsm(Module* P0,char* P1) {
+ return (void)P0->setModuleInlineAsm(P1);
+}
+
+Function* Module_getNamedFunction(Module* P0,char* P1) {
+ return (Function*)P0->getNamedFunction(P1);
+}
+
+Function* Module_getOrInsertFunction(Module* P0,char* P1,FunctionType* P2) {
+ return (Function*)P0->getOrInsertFunction(P1,P2);
+}
+
+
+
+
+// end of llvm.cpp
Added: pypy/dist/pypy/translator/llvm/wrapable/libllvm.h
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/wrapable/libllvm.h Thu Apr 20 16:17:39 2006
@@ -0,0 +1,63 @@
+#ifndef __llvm_H__
+#define __llvm_H__
+
+#include "llvm/Module.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/Function.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Type.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+
+using namespace llvm;
+#define TypeID int
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ExecutionEngine
+ExecutionEngine* ExecutionEngine_create(ModuleProvider*,long);
+Module& ExecutionEngine_getModule(ExecutionEngine*);
+void ExecutionEngine_freeMachineCodeForFunction(ExecutionEngine*,Function*);
+GenericValue ExecutionEngine_runFunction(ExecutionEngine*,Function*,GenericValue*);
+
+// ModuleProvider
+
+// ExistingModuleProvider
+ExistingModuleProvider* ExistingModuleProvider___init__(Module*);
+
+// Function
+void Function_eraseFromParent(Function*);
+FunctionType* Function_getFunctionType(Function*);
+
+// FunctionType
+
+// GenericValue
+
+// TypeID
+
+// Type
+TypeID* Type_getTypeID(Type*);
+Type* Type_getContainedType(Type*,long);
+char* Type_getDescription(Type*);
+
+// Module
+Module* Module___init__(char*);
+char* Module_getModuleIdentifier(Module*);
+void Module_setModuleIdentifier(Module*,char*);
+char* Module_getTargetTriple(Module*);
+void Module_setTargetTriple(Module*,char*);
+char* Module_getModuleInlineAsm(Module*);
+void Module_setModuleInlineAsm(Module*,char*);
+Function* Module_getNamedFunction(Module*,char*);
+Function* Module_getOrInsertFunction(Module*,char*,FunctionType*);
+
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __llvm_H__
Added: pypy/dist/pypy/translator/llvm/wrapable/llvm.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/wrapable/llvm.py Thu Apr 20 16:17:39 2006
@@ -0,0 +1,154 @@
+# llvm.py
+
+from wrapper import Wrapper
+from ctypes import *
+import llvm_helper
+
+
+llvm = cdll.load('libllvm.so')
+STRING = c_char_p
+
+class ExecutionEngine(Wrapper):
+ def __init__(P0,P1,P2=False):
+ P0.instance = llvm_helper.ExecutionEngine___init__(P0,P1,P2)
+
+ def create(P0,P1=False):
+ return llvm.ExecutionEngine_create(P0,P1)
+ create = staticmethod(create)
+
+ def getModule(P0):
+ return llvm.ExecutionEngine_getModule(P0)
+
+ def freeMachineCodeForFunction(P0,P1):
+ return llvm.ExecutionEngine_freeMachineCodeForFunction(P0,P1)
+
+ def runFunction(P0,P1,P2):
+ return llvm.ExecutionEngine_runFunction(P0,P1,P2)
+
+class ModuleProvider(Wrapper):
+ pass
+
+class ExistingModuleProvider(Wrapper):
+ def __init__(P0,P1):
+ P0.instance = llvm.ExistingModuleProvider___init__(P1)
+
+class Function(Wrapper):
+ def eraseFromParent(P0):
+ return llvm.Function_eraseFromParent(P0)
+
+ def getFunctionType(P0):
+ return llvm.Function_getFunctionType(P0)
+
+class FunctionType(Wrapper):
+ pass
+
+class GenericValue(Wrapper):
+ pass
+
+class TypeID(Wrapper):
+ pass
+
+class Type(Wrapper):
+ def getTypeID(P0):
+ return llvm.Type_getTypeID(P0)
+
+ def getContainedType(P0,P1):
+ return llvm.Type_getContainedType(P0,P1)
+
+ def getDescription(P0):
+ return llvm.Type_getDescription(P0)
+
+class Module(Wrapper):
+ def __init__(P0,P1='mymodule'):
+ P0.instance = llvm.Module___init__(P1)
+
+ def getModuleIdentifier(P0):
+ return llvm.Module_getModuleIdentifier(P0)
+
+ def setModuleIdentifier(P0,P1='myothermodule'):
+ return llvm.Module_setModuleIdentifier(P0,P1)
+
+ def getTargetTriple(P0):
+ return llvm.Module_getTargetTriple(P0)
+
+ def setTargetTriple(P0,P1):
+ return llvm.Module_setTargetTriple(P0,P1)
+
+ def getModuleInlineAsm(P0):
+ return llvm.Module_getModuleInlineAsm(P0)
+
+ def setModuleInlineAsm(P0,P1):
+ return llvm.Module_setModuleInlineAsm(P0,P1)
+
+ def getNamedFunction(P0,P1):
+ return llvm.Module_getNamedFunction(P0,P1)
+
+ def getOrInsertFunction(P0,P1,P2):
+ return llvm.Module_getOrInsertFunction(P0,P1,P2)
+
+ def n_functions(P0):
+ return llvm_helper.n_functions(P0)
+
+ def function_exists(P0,P1='myfunction'):
+ return llvm_helper.function_exists(P0,P1)
+
+llvm.ExecutionEngine_create.restype = ExecutionEngine
+llvm.ExecutionEngine_create.argtypes = [ModuleProvider,c_long]
+
+llvm.ExecutionEngine_getModule.restype = Module
+llvm.ExecutionEngine_getModule.argtypes = [ExecutionEngine]
+
+llvm.ExecutionEngine_freeMachineCodeForFunction.restype = None
+llvm.ExecutionEngine_freeMachineCodeForFunction.argtypes = [ExecutionEngine,Function]
+
+llvm.ExecutionEngine_runFunction.restype = GenericValue
+llvm.ExecutionEngine_runFunction.argtypes = [ExecutionEngine,Function,GenericValue]
+
+llvm.ExistingModuleProvider___init__.restype = ExistingModuleProvider
+llvm.ExistingModuleProvider___init__.argtypes = [Module]
+
+llvm.Function_eraseFromParent.restype = None
+llvm.Function_eraseFromParent.argtypes = [Function]
+
+llvm.Function_getFunctionType.restype = FunctionType
+llvm.Function_getFunctionType.argtypes = [Function]
+
+llvm.Type_getTypeID.restype = TypeID
+llvm.Type_getTypeID.argtypes = [Type]
+
+llvm.Type_getContainedType.restype = Type
+llvm.Type_getContainedType.argtypes = [Type,c_long]
+
+llvm.Type_getDescription.restype = STRING
+llvm.Type_getDescription.argtypes = [Type]
+
+llvm.Module___init__.restype = Module
+llvm.Module___init__.argtypes = [STRING]
+
+llvm.Module_getModuleIdentifier.restype = STRING
+llvm.Module_getModuleIdentifier.argtypes = [Module]
+
+llvm.Module_setModuleIdentifier.restype = None
+llvm.Module_setModuleIdentifier.argtypes = [Module,STRING]
+
+llvm.Module_getTargetTriple.restype = STRING
+llvm.Module_getTargetTriple.argtypes = [Module]
+
+llvm.Module_setTargetTriple.restype = None
+llvm.Module_setTargetTriple.argtypes = [Module,STRING]
+
+llvm.Module_getModuleInlineAsm.restype = STRING
+llvm.Module_getModuleInlineAsm.argtypes = [Module]
+
+llvm.Module_setModuleInlineAsm.restype = None
+llvm.Module_setModuleInlineAsm.argtypes = [Module,STRING]
+
+llvm.Module_getNamedFunction.restype = Function
+llvm.Module_getNamedFunction.argtypes = [Module,STRING]
+
+llvm.Module_getOrInsertFunction.restype = Function
+llvm.Module_getOrInsertFunction.argtypes = [Module,STRING,FunctionType]
+
+
+
+# end of llvm.py
Added: pypy/dist/pypy/translator/llvm/wrapable/llvm_helper.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/wrapable/llvm_helper.py Thu Apr 20 16:17:39 2006
@@ -0,0 +1,16 @@
+#Module helper methods
+def n_functions(self): #TODO
+ return 0
+
+def function_exists(self, name): #TODO
+ return False
+
+#ExecutionEngine helper methods
+def ExecutionEngine___init__(self, mp, ForceInterpreter=False):
+ return self.create(mp, ForceInterpreter)
+
+def delete(self, fnname):
+ mod = self.getModule()
+ f = mod.getNamedFunction(fnname) # XXX handle fnname not found?
+ self.freeMachineCodeForFunction(f) # still no-op on march 27th 2006
+ f.eraseFromParent()
Added: pypy/dist/pypy/translator/llvm/wrapable/setup.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/wrapable/setup.py Thu Apr 20 16:17:39 2006
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+
+from distutils.core import setup
+from distutils.extension import Extension
+from os import popen
+import sys
+
+
+if len(sys.argv) <= 1:
+ print 'usage: setup.py <module_name> .... (the usual setup.py options)'
+ sys.exit()
+module_name = sys.argv[1]
+del sys.argv[1]
+
+cxxflags = popen('llvm-config --cxxflags').readline().split()
+ldflags = popen('llvm-config --ldflags').readline().split()
+libs = popen('llvm-config --libs all').readline().split()
+
+opts = dict(name=module_name,
+ sources=[module_name + '.cpp'],
+ libraries=[],
+ include_dirs =["include"] + [f[2:] for f in cxxflags if f.startswith('-I')],
+ library_dirs =[f[2:] for f in ldflags if f.startswith('-L')],
+ define_macros=[(f[2:], None) for f in cxxflags if f.startswith('-D')],
+ extra_objects=libs)
+
+ext_modules = Extension(**opts)
+
+setup(name=opts['name'], ext_modules=[ext_modules])
Added: pypy/dist/pypy/translator/llvm/wrapable/test/test_llvm.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/wrapable/test/test_llvm.py Thu Apr 20 16:17:39 2006
@@ -0,0 +1,99 @@
+import py
+from pypy.translator.llvm.wrapable.llvm import *
+
+
+#XXX The tests below were shamefully never written when writing the rest of the code and
+# should therefor be filled in by Eric asap.
+
+def test_misc():
+ print 'Module("mine")'
+ mod = Module('mine')
+ print 'mod=', mod
+ print 'mod.instance=', mod.instance
+ print
+ assert mod.n_functions() == 0
+
+ print 'ExistingModuleProvider(mod)'
+ mp = ExistingModuleProvider(mod)
+ print 'mp=', mp
+ print 'mp.instance=', mp.instance
+ print
+
+ ee = ExecutionEngine(mp)
+ #ee = ExecutionEngine.create(mp) #same
+ print 'ee=', ee
+ #print 'ee.instance=', ee.instance #can't do here because ee.create is staticmethod
+ mod2 = ee.getModule()
+ print mod2
+
+ print 'mod.getModuleIdentifier()'
+ modId = mod.getModuleIdentifier()
+ print 'modId=', modId
+ assert modId == 'mine'
+ assert modId == mod2.getModuleIdentifier()
+
+def test_wrapable_create():
+ pass
+
+def test_global_function():
+ pass
+
+def test_class():
+ pass
+
+def test_class_ctor():
+ pass
+
+def test_class_dtor():
+ pass
+
+def test_method():
+ pass
+
+def test_staticmethod():
+ pass
+
+def test_staticmethod_as_factory(): #self.instance can not be set in this case
+ pass
+
+def test_classmethod():
+ pass
+
+def test_include():
+ pass
+
+def test_include_py():
+ pass
+
+def test_call_pymethod():
+ pass
+
+def test_call_pyctor():
+ pass
+
+def test_call_pystaticmethod():
+ pass
+
+def test_call_pyclassmethod():
+ pass
+
+def test_call_pyfunction():
+ pass
+
+def test_cpp_cast():
+ pass
+
+def test_py_cast():
+ pass
+
+def test_enum():
+ pass
+
+def test_structure():
+ pass
+
+def test_ref_ptr_inst():
+ pass
+
+def test_default_arguments():
+ pass
Added: pypy/dist/pypy/translator/llvm/wrapable/wrap_llvm.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/wrapable/wrap_llvm.py Thu Apr 20 16:17:39 2006
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+
+from wrapable import *
+from ctypes import *
+
+
+# All the classes we wrap in the module...
+Global = Wglobal()
+ExecutionEngine = Wclass('ExecutionEngine' , [])
+ModuleProvider = Wclass('ModuleProvider' , [])
+ExistingModuleProvider = Wclass('ExistingModuleProvider', [ModuleProvider])
+Function = Wclass('Function' , [])
+FunctionType = Wclass('FunctionType' , [])
+GenericValue = Wclass('GenericValue' , [])
+TypeID = Enum('TypeID' , [])
+Type = Wclass('Type' , [])
+Module = Wclass('Module' , [])
+
+# Helper functions
+as_c_string = CppCast('as_c_string', STRING)
+as_std_string = CppCast('as_std_string', STRING)
+as_vector_GenericValue = CppCast('as_vector_GenericValue', GenericValue)
+
+# All the functions (XXX not working/output yet)
+Global\
+ .add(Wfunction(None , 'ParseAssemblyString', [Module, STRING]))\
+ .add(Wfunction(c_int, 'verifyModule' , [Module]))
+
+# All the methods each class contains...
+ExecutionEngine\
+ .add(Wctor(ExecutionEngine, [ModuleProvider,c_int], [False],\
+ 'llvm_helper.ExecutionEngine___init__'))\
+ .add(Wstaticmethod(ExecutionEngine, 'create', [ModuleProvider,c_int], [False]))\
+ .add(Wmethod(Ref(Module) , 'getModule', []))\
+ .add(Wmethod(None , 'freeMachineCodeForFunction', [Function]))\
+ .add(Wmethod(Inst(GenericValue) , 'runFunction', [Function,as_vector_GenericValue]))
+
+ExistingModuleProvider\
+ .add(Wctor(ExistingModuleProvider, [Module]))
+
+Function\
+ .add(Wmethod(None , 'eraseFromParent', []))\
+ .add(Wmethod(FunctionType, 'getFunctionType', []))
+
+Type\
+ .add(Wmethod(TypeID , 'getTypeID', []))\
+ .add(Wmethod(Type , 'getContainedType', [c_int]))\
+ .add(Wmethod(as_c_string , 'getDescription', []))
+
+Module\
+ .add(Wctor(Module, [as_std_string], ['mymodule']))\
+ .add(Wmethod(as_c_string , 'getModuleIdentifier', []))\
+ .add(Wmethod(None , 'setModuleIdentifier', [STRING], ['myothermodule']))\
+ .add(Wmethod(as_c_string , 'getTargetTriple', []))\
+ .add(Wmethod(None , 'setTargetTriple', [STRING]))\
+ .add(Wmethod(as_c_string , 'getModuleInlineAsm', []))\
+ .add(Wmethod(None , 'setModuleInlineAsm', [STRING]))\
+ .add(Wmethod(Function , 'getNamedFunction', [STRING]))\
+ .add(Wmethod(Function , 'getOrInsertFunction', [STRING, FunctionType]))\
+ .add(Wmethod(c_int , 'llvm_helper.n_functions', []))\
+ .add(Wmethod(c_int , 'llvm_helper.function_exists', [STRING], ['myfunction']))
+
+# Create the module...
+Wroot('llvm')\
+ .include('llvm/Module.h')\
+ .include('llvm/ModuleProvider.h')\
+ .include('llvm/Function.h')\
+ .include('llvm/DerivedTypes.h')\
+ .include('llvm/Type.h')\
+ .include('llvm/Analysis/Verifier.h')\
+ .include('llvm/ExecutionEngine/ExecutionEngine.h')\
+ .include('llvm/ExecutionEngine/GenericValue.h')\
+ .include('llvm_helper.py')\
+ .add(Global)\
+ .add(ExecutionEngine)\
+ .add(ModuleProvider)\
+ .add(ExistingModuleProvider)\
+ .add(Function)\
+ .add(FunctionType)\
+ .add(GenericValue)\
+ .add(TypeID)\
+ .add(Type)\
+ .add(Module)\
+ .create()
Added: pypy/dist/pypy/translator/llvm/wrapable/wrapable.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/wrapable/wrapable.py Thu Apr 20 16:17:39 2006
@@ -0,0 +1,396 @@
+import types
+from ctypes import *
+
+STRING = c_char_p
+
+def log(msg):
+ print msg
+ pass
+
+
+class T(object):
+ def __init__(self, item):
+ self.item = item
+class Inst(T): pass
+class Ref(T): pass
+#class Ptr(T): pass
+
+
+class Cast(object):
+ def __init__(self, cppfunc, item):
+ self.cppfunc = cppfunc
+ self.item = item
+class CppCast(Cast): pass
+#class PyCast(Cast): pass
+
+
+class _CTypesInfo(object):
+ def __init__(self, ctypesname, cppname):
+ self.ctypesname = ctypesname
+ self.cppname = cppname
+
+_ctypesinfo = {
+ None : _CTypesInfo('None' , 'void'),
+ c_char : _CTypesInfo('c_char' , 'char'),
+ c_byte : _CTypesInfo('c_byte' , 'char'),
+ c_ubyte : _CTypesInfo('c_ubyte' , 'unsigned char'),
+ c_short : _CTypesInfo('c_short' , 'short'),
+ c_ushort : _CTypesInfo('c_ushort' , 'unsigned short'),
+ c_int : _CTypesInfo('c_int' , 'int'),
+ c_uint : _CTypesInfo('c_uint' , 'unsigned int'),
+ c_long : _CTypesInfo('c_long' , 'long'),
+ c_ulong : _CTypesInfo('c_ulong' , 'unsigned long'),
+ c_longlong : _CTypesInfo('c_longlong' , 'long long'),
+ c_ulonglong : _CTypesInfo('c_ulonglong', 'unsigned long long'),
+ c_float : _CTypesInfo('c_float' , 'float'),
+ c_double : _CTypesInfo('c_double' , 'double'),
+ c_char_p : _CTypesInfo('STRING' , 'char*'),
+ c_wchar_p : _CTypesInfo('c_wchar_p' , 'wchar_t*'),
+ c_void_p : _CTypesInfo('c_void_p' , 'void*'),
+ }
+
+def _ctypes_type(t):
+ if isinstance(t, Cast):
+ t = t.item
+ if t in _ctypesinfo:
+ return _ctypesinfo[t].ctypesname
+ if isinstance(t, Wclass):
+ return t.name
+ if isinstance(t, (Inst, Ref)) and isinstance(t.item, Wclass):
+ return t.item.name
+ raise TypeError('unknown type %s' % t)
+
+
+def _cpp_type(t):
+ if isinstance(t, Cast):
+ t = t.item
+ if t in _ctypesinfo:
+ return _ctypesinfo[t].cppname
+ if isinstance(t, Wclass):
+ return t.name + '*'
+ if isinstance(t, Inst):
+ return t.item.name
+ if isinstance(t, Ref) and isinstance(t.item, Wclass):
+ return t.item.name + '&'
+ raise TypeError('unknown type %s' % t)
+h_type = _cpp_type
+
+
+class _Witem(object):
+ def __init__(self):
+ self.items = []
+
+ def add(self, item):
+ self.items.append(item)
+ return self
+
+ def header(self):
+ pass
+
+ def cpp(self):
+ pass
+
+ def py(self):
+ pass
+
+ def finish_declaration(self, parent_item):
+ for item in self.items:
+ item.finish_declaration(self)
+
+
+class Wfunction(_Witem):
+ def __init__(self, ret, name, param):
+ super(Wfunction, self).__init__()
+ self.ret = ret
+ self.name = name
+ self.param = param
+
+
+class Wmethod(_Witem):
+ def __init__(self, ret, name, param, defaults=[]):
+ super(Wmethod, self).__init__()
+ self.ret = ret
+ self.name = name
+ self.param = param
+ self.defaults = defaults
+ self._self_was_added = False
+
+ def finish_declaration(self, parent_item):
+ super(Wmethod, self).finish_declaration(parent_item)
+ if not self._self_was_added and not isinstance(self, Wstaticmethod):
+ self.param.insert(0, parent_item)
+ self._self_was_added = True
+
+ def _is_pyfunc(self):
+ return '.' in self.name
+
+ def _plain_name(self):
+ if self._is_pyfunc():
+ return self.name.split('.',1)[1]
+ return self.name
+
+ def _callee_name(self, namespace, funcname):
+ if self._is_pyfunc():
+ return self.name
+ return '%s.%s_%s' % (namespace, funcname, self.name)
+
+
+class Wstaticmethod(Wmethod):
+ pass
+
+
+class Wctor(Wmethod): #Wrapped constructor
+ #XXX I don't like the fact that the returntype needs to be specified.
+ # We need to somehow keep a link to the parent!
+ # (maybe set a parent attribute in the .add methods?)
+ def __init__(self, ret, param, defaults=[], name='__init__'):
+ #note: The order is different from Wmethod because name would seldomly be supplied.
+ # Probably this will only happen when a Python function should be called instead.
+ super(Wctor, self).__init__(ret, name, param, defaults)
+
+
+class Wclass(_Witem):
+ def __init__(self, name, parents=[]):
+ super(Wclass, self).__init__()
+ self.name = name
+ self.parents = parents
+Enum = Wclass #XXX temporary hack
+
+
+class Wglobal(_Witem):
+ pass
+
+
+class Wroot(_Witem): #root wrapable object
+
+ header_template = '''#ifndef __%(name)s_H__
+#define __%(name)s_H__
+
+%(includes)s
+using namespace %(namespace)s;
+#define TypeID int
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+%(code)s
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __%(name)s_H__
+'''
+
+ cpp_template = '''// %(name)s.cpp
+
+#include "lib%(name)s.h"
+
+// Helper functions (mostly for casting returnvalues and parameters)
+char* as_c_string(std::string str) {
+ return (char*)str.c_str();
+}
+
+std::string as_std_string(char* p) {
+ return std::string(p);
+}
+
+std::vector<GenericValue> as_vector_GenericValue(GenericValue* gv) {
+ std::vector<GenericValue> gvv;
+ gvv.push_back(*gv);
+ return gvv;
+}
+
+%(code)s
+
+// end of %(name)s.cpp
+'''
+
+ py_template = '''# %(name)s.py
+
+from wrapper import Wrapper
+from ctypes import *
+%(includes)s
+
+%(name)s = cdll.load('lib%(name)s.so')
+STRING = c_char_p
+
+%(code)s
+
+# end of %(name)s.py
+'''
+
+ def __init__(self, name):
+ super(Wroot, self).__init__()
+ self.name = name
+ self.includes = []
+ log('Creating %s module' % name)
+
+ def include(self, include):
+ self.includes.append(include)
+ return self #to allow chaining
+
+ def header(self):
+ name = self.name
+ code = ''
+
+ includes = ''
+ for include in self.includes:
+ if include.endswith('.h'):
+ includes += '#include "%s"\n' % include
+
+ namespace = self.name #XXX
+
+ for item in self.items:
+ if isinstance(item, Wglobal):
+ continue
+ code += '// %s\n' % item.name
+ for method in item.items:
+ if method._is_pyfunc():
+ continue
+ restype = h_type(method.ret)
+ argtypes = [h_type(p) for p in method.param]
+ if isinstance(method, Wctor):
+ del argtypes[0]
+ code += '%s %s_%s(%s);\n' % (restype, item.name, method.name, ','.join(argtypes))
+ code += '\n'
+
+ return self.header_template % locals()
+
+ def _casted_arg(self, i, arg):
+ if isinstance(arg, CppCast):
+ return '%s(P%d)' % (arg.cppfunc, i)
+ return 'P%d' % i
+
+ def cpp(self):
+ name = self.name
+ code = ''
+ for item in self.items:
+ if isinstance(item, Wglobal):
+ continue
+ code += '// %s\n' % item.name
+ for method in item.items:
+ if method._is_pyfunc():
+ continue
+ restype = _cpp_type(method.ret)
+ param = method.param[isinstance(method, Wctor):]
+ argtypes = ['%s P%d' % (_cpp_type(p),i) for i,p in enumerate(param)]
+ code += '%s %s_%s(%s) {\n' % (restype, item.name, method.name, ','.join(argtypes))
+ #for i,p in enumerate(method.param):
+ # code += ' %s p%d = (%s)P%d;\n' % (_cpp_type(p), i, _cpp_type(p), i)
+ retcast = '(%s)' % restype
+ if isinstance(method.ret, CppCast):
+ retcast_pre = '%s(' % method.ret.cppfunc
+ retcast_post = ')'
+ else:
+ retcast_pre = ''
+ retcast_post = ''
+ if isinstance(method, Wstaticmethod):
+ args = [self._casted_arg(i,p) for i,p in enumerate(method.param)]
+ code += ' return %s%s%s::%s(%s)%s;\n}\n\n' % \
+ (retcast, retcast_pre, item.name, method.name,
+ ','.join(args), retcast_post)
+ elif isinstance(method, Wctor):
+ #args = [self._casted_arg(i+1,p) for i,p in enumerate(method.param[1:])]
+ args = [self._casted_arg(i,p) for i,p in enumerate(param)]
+ code += ' return %snew %s(%s)%s;\n}\n\n' % \
+ (retcast_pre, item.name, ','.join(args), retcast_post)
+ else:
+ args = [self._casted_arg(i+1,p) for i,p in enumerate(method.param[1:])]
+ code += ' return %s%sP0->%s(%s)%s;\n}\n\n' % \
+ (retcast, retcast_pre, method.name,
+ ','.join(args), retcast_post)
+ code += '\n'
+ return self.cpp_template % locals()
+
+ def py(self):
+ name = self.name
+ code = ''
+
+ includes = ''
+ for include in self.includes:
+ if include.endswith('.py'):
+ includes += 'import %s\n' % include[:-3]
+
+ # output classes, methods, etc.
+ for item in self.items:
+ if isinstance(item, Wglobal):
+ continue
+ code += 'class %s(Wrapper):\n' % item.name
+ for method in item.items:
+ param = ['P%d' % i for i,p in enumerate(method.param)]
+ plain_name = method._plain_name()
+ callee_name = method._callee_name(self.name, item.name)
+ params = ''
+ for i, p in enumerate(param):
+ if params:
+ params += ','
+ params += p
+ n = len(method.defaults) - len(param) + i
+ if n >= 0:
+ params += '=' + repr(method.defaults[n])
+ if isinstance(method, Wctor):
+ #We made sure the header and cpp file constructors don't get the python 'self'.
+ #Now we have to make sure we only pass 'self' to python helpers.
+ code += ' def __init__(%s):\n' % params
+ code += ' P0.instance = %s(%s)\n' % (
+ callee_name, ','.join(param[not method._is_pyfunc():]))
+ else:
+ code += ' def %s(%s):\n' % (plain_name, params)
+ code += ' return %s(%s)\n' % (
+ callee_name, ','.join(param))
+ if isinstance(method, Wstaticmethod):
+ code += ' %s = staticmethod(%s)\n' % (plain_name, plain_name)
+ code += '\n'
+ if not item.items:
+ code += ' pass\n\n'
+
+ # output return and parameter (c)types
+ for item in self.items:
+ if isinstance(item, Wglobal):
+ continue
+ for method in item.items:
+ if method._is_pyfunc():
+ continue
+ n = int(isinstance(method, Wctor))
+ restype = _ctypes_type(method.ret)
+ argtypes = ','.join([_ctypes_type(p) for p in method.param[n:]])
+ if isinstance(method, Wstaticmethod):
+ im_func = ''
+ else:
+ im_func = 'im_func.'
+ code += 'llvm.%s_%s.restype = %s\n' % (
+ item.name, method.name, restype)
+ code += 'llvm.%s_%s.argtypes = [%s]\n\n' % (
+ item.name, method.name, argtypes)
+
+ return self.py_template % locals()
+
+ def create_files(self):
+ log('Creating ' + self.name + '.py')
+ f = open(self.name + '.py', 'w')
+ code = self.py()
+ f.write(code)
+ f.close()
+
+ log('Creating lib' + self.name + '.h')
+ f = open('lib' + self.name + '.h', 'w')
+ code = self.header()
+ f.write(code)
+ f.close()
+
+ log('Creating lib' + self.name + '.cpp')
+ f = open('lib' + self.name + '.cpp', 'w')
+ code = self.cpp()
+ f.write(code)
+ f.close()
+
+ def create_library(self):
+ from os import system
+ system('python setup.py lib%s build_ext -i' % self.name)
+
+ def create(self):
+ self.finish_declaration(None)
+ self.create_files()
+ self.create_library()
Added: pypy/dist/pypy/translator/llvm/wrapable/wrapper.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/wrapable/wrapper.py Thu Apr 20 16:17:39 2006
@@ -0,0 +1,19 @@
+from ctypes import c_int
+
+
+class Wrapper(c_int): #c_int because it needs to be a ctypes datatype for from_param to work
+ def from_param(cls, p):
+ try:
+ return p.instance
+ except:
+ #XXX This might happen if we use a staticmethod (factory) to create a function.
+ # In that case we have no 'self' to store the instance in.
+ # An example of this can be found in wrap_llvm.py/ExecutionEngine.create
+ return p
+ from_param = classmethod(from_param)
+
+ #def errcheck(retval, function, arguments):
+ # print 'Wrapper.errcheck: retval(instance)=%s, function=%s %s, arguments=%s' % (retval,function,dir(function.__class__),arguments)
+ # self.instance = retval
+ # return retval
+ #errcheck = staticmethod(errcheck)
More information about the Pypy-commit
mailing list