Advertisement
Guest User

libblender.py

a guest
Sep 23rd, 2010
237
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.08 KB | None | 0 0
  1. #!/usr/bin/python
  2. '''
  3. libblender test1 - segfaults on WM_init()
  4. by Harts Antler | Sept 2010 | bhartsho@yahoo.com
  5. License: LGPL
  6.  
  7. Notes:
  8.     1. after editing CMakeLists.txt, run: cmake -G "Unix Makefiles" ../blender
  9.     2. game engine must be turned off, line 76: OPTION(WITH_GAMEENGINE    "Enable Game Engine" OFF)
  10.     3. minimal ubuntu setup: apt-get install libxi-dev libopenexr-dev libopenjpeg-dev libsamplerate-dev
  11.     4. blender/source/creator/CMakeLists.txt        - thanks to IdeasMan!
  12.         change: ADD_EXECUTABLE(blender ${EXETYPE} ${EXESRC})
  13.         to: ADD_LIBRARY(blender SHARED ${EXETYPE} ${EXESRC})
  14.     5. build libblender
  15.  
  16. RPython Notes:
  17.     6. link or copy libblender.so to /usr/lib/
  18.         cd /usr/lib
  19.         sudo ln -s /path/to/my/build/lib/libblender.so
  20.     7. download pypy source code, set PATH2PYPY below
  21. '''
  22.  
  23. BLENDER_SOURCE = '../blender'
  24. PATH2PYPY = '../pypy-trunk'
  25. import os, sys, time, math
  26. sys.path.append(PATH2PYPY)
  27.  
  28. if '--compile' in sys.argv:     # compiles RPython
  29.     os.system( 'python %s/pypy/translator/goal/translate.py %s' %(PATH2PYPY, sys.argv[0] ) )
  30.     sys.exit()
  31.  
  32. USE_CTYPES = False
  33. if '--ctypes' in sys.argv: USE_CTYPES = True
  34.  
  35. import ctypes
  36. from ctypes import *
  37. _libblender = ctypes.CDLL('lib/libblender.so')
  38. # undefined symbol: _ZN10KX_RayCast9reportHitEP17PHY_RayCastResult
  39. # if you get the error above you need to compile libblender with out the game engine
  40. print 'ctypes can load libblender', _libblender
  41.  
  42. # Helper function for declaring function prototypes
  43. def cfunc(name, result, *args):
  44.     """Build and apply a ctypes prototype complete with parameter flags"""
  45.     atypes = []
  46.     aflags = []
  47.     for arg in args:
  48.         atypes.append(arg[1])
  49.         aflags.append((arg[2], arg[0]) + arg[3:])
  50.     return CFUNCTYPE(result, *atypes)((name, _libblender), tuple(aflags))
  51.  
  52. def test_ctypes():
  53.     main = cfunc('main', c_int, ('argc', c_int, 1), ('argv', POINTER(c_char_p), 1) )
  54.     argv = (c_char_p * len(sys.argv))()
  55.     for i, arg in enumerate( sys.argv ): argv[ i ] = arg
  56.     argv[0] = 'blender'
  57.     argc = c_int( len(sys.argv) )
  58.     #main( ctypes.byref(argc), argv )
  59.     main( argc, argv )      # this segfaults, why?
  60.  
  61. # need help!!! #
  62. test_ctypes()       # segfaults, most likely WM_init, why?
  63.  
  64. ####### RPython below ##########
  65. sys.exit()      # comment if you want to try building with RPython and rffi
  66.  
  67. from pypy.rpython.lltypesystem import lltype, rffi
  68. from pypy.rpython.tool import rffi_platform as platform
  69. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  70. from pypy.rpython.annlowlevel import llhelper       # thanks Forgeot d'Arc
  71.  
  72.  
  73. _problem_headers_ = 'smoke_API.h MEM_RefCountPtr.h MEM_NonCopyable.h MEM_RefCounted.h MEM_SmartPtr.h MEM_Allocator.h MEM_CacheLimiter.h BSP_MeshPrimitives.h BSP_CSGMesh.h BOP_Interface.h CTR_TaggedIndex.h BSP_CSGMesh.h STR_String.h GHOST_Rect.h GHOST_IWindow.h GHOST_ITimerTask.h GHOST_ISystem.h GHOST_IEvent.h GHOST_IEventConsumer.h STR_HashedString.h CTR_Map.h CTR_TaggedSetOps.h CTR_List.h CTR_UHeap.h'.split()
  74.  
  75. _problem_headers_ += 'BLI_vfontdata.h BLI_editVert.h BLI_bpath.h BLI_graph.h BLI_ghash.h BLI_blenlib.h BLI_listbase.h RNA_define.h RNA_access.h'.split()
  76.  
  77. _rpy_conflicts_ = 'mmap_win.h'.split()
  78.  
  79. _problem_headers_ += _rpy_conflicts_
  80.  
  81. def find_blender_headers():
  82.     headers = []
  83.     paths = []
  84.     internal = os.path.join( BLENDER_SOURCE, 'intern' )     # would be nice to have a blender.h at this level that included everything
  85.     for name in os.listdir( internal ):
  86.         #if name == 'guardedalloc': continue        # conflicts with RPython memory allocations - not useful anyways?
  87.         print name
  88.         a = os.path.join( internal, name )
  89.         if os.path.isdir( a ):      # audaspace, boolop, bsp, container, decimation, elbeem, ghost, guardedalloc, iksolver, itasc, make, memutil, moto, etc...
  90.             for name in os.listdir( a ):
  91.                 b = os.path.join( a,name )
  92.                 # there can be headers at this level, container for example: CTR_Map.h
  93.                 if os.path.isfile( b ) and b.endswith('.h') and name not in _problem_headers_:     
  94.                     headers.append( b )
  95.                     if a not in paths: paths.append( a )
  96.  
  97.                 elif os.path.isdir( b ) and name == 'extern':       # only wrap externals?
  98.                     for name in os.listdir( b ):
  99.                         c = os.path.join( b, name )
  100.                         if os.path.isfile( c ) and c.endswith('.h') and name not in _problem_headers_:
  101.                             headers.append( c )
  102.                             if b not in paths: paths.append( b )
  103.     h = []; p = []
  104.     for a in headers: print a; h.append( os.path.abspath(a) )
  105.     for a in paths: p.append( os.path.abspath(a) )
  106.     return h, p
  107.  
  108. headers, paths = find_blender_headers()
  109. #for name in 'blenlib makesrna render imbuf blenkernel'.split():
  110. for name in 'blenlib makesrna render imbuf'.split():
  111.     a = os.path.join( BLENDER_SOURCE, 'source' )
  112.     b = os.path.join( a, 'blender' )
  113.     c = os.path.join( b, name )
  114.     paths.append( os.path.abspath(c) )
  115.     for f in os.listdir( c ):
  116.         if f.endswith( '.h' ) and f not in _problem_headers_: headers.append( f ); print f
  117.  
  118. ugly_hacks = '''
  119. struct bContext;
  120. typedef struct bContext bContext;
  121.  
  122. '''
  123.  
  124. eci = ExternalCompilationInfo(
  125.     includes = headers,
  126.     include_dirs = paths,
  127.     #link_files = [ os.path.abspath('lib/libblender.so') ],
  128.     link_files = [ '/usr/lib/libblender.so' ],      # required
  129.     separate_module_sources=[ugly_hacks]        # can inject C code here
  130. )
  131. platform.verify_eci(eci)
  132.  
  133. _rffi_ctypes_mapping = {
  134.     rffi.INT : ctypes.c_int,
  135.     rffi.UINT : ctypes.c_uint,
  136. }
  137.  
  138. def external(name, args=[], result=lltype.Void):        # if function takes void then args=[], not args=[lltype.Void]
  139.     if USE_CTYPES:
  140.         if result in _rffi_ctypes_mapping: result = _rffi_ctypes_mapping[ result ]
  141.         else: result = ctypes.c_void_p
  142.         a = []
  143.         for arg in args:
  144.             if arg in _rffi_ctypes_mapping: a.append( _rffi_ctypes_mapping[ arg ] )
  145.             else: a.append( ctypes.c_void_p )
  146.         proto = ctypes.CFUNCTYPE( result, *tuple(a) )
  147.         func = proto( (name, _libblender) )
  148.         return func
  149.     else:       # RPython - rffi
  150.         return rffi.llexternal(name, args, result, compilation_info=eci)
  151.  
  152. #charpp = rffi.CArrayPtr( rffi.CCHARP )
  153.  
  154. # blender/source/blender/blenkernel/BKE_context.h
  155. bContext    = rffi.CStructPtr('bContext')
  156. CTX_create      = external( 'CTX_create',       result=bContext)
  157. #CTX_free           = external( 'CTX_free',     [bContext],     lltype.Void)
  158. #CTX_copy       = external( 'CTX_copy',     [bContext],     bContext_ptr)
  159.  
  160. # blender/source/blender/blenlib/BLI_threads.h
  161. BLI_threadapi_init  = external('BLI_threadapi_init')
  162. # blender/source/blender/makesrns/RNA_types.h
  163. BlenderRNA_ptr = rffi.CStructPtr('BlenderRNA')
  164. ParameterList_ptr = rffi.CStructPtr('ParameterList')
  165. FunctionRNA_ptr = rffi.CStructPtr('FunctionRNA')
  166. PropertyRNA_ptr = rffi.CStructPtr('PropertyRNA')
  167. StructRNA_ptr = rffi.CStructPtr('StructRNA')
  168. IDProperty_ptr = rffi.CStructPtr('IDProperty')
  169. IDProperty_ptr = rffi.CStructPtr('IDProperty')
  170. ReportList_ptr = rffi.CStructPtr('ReportList')
  171.  
  172. # blender/source/blender/makesrns/RNA_define.h
  173. RNA_init        = external('RNA_init' )
  174. RNA_create  = external('RNA_create', result=BlenderRNA_ptr )
  175. RNA_free    = external('RNA_free', [ BlenderRNA_ptr ] )
  176.  
  177. # blender/source/blender/render/RE_pipeline.h
  178. RE_engines_init  = external('RE_engines_init' )
  179.  
  180. # blender/source/blender/imbuf/IMB_imbuf.h
  181. IMB_init  = external('IMB_init' )
  182.  
  183.  
  184. # blender/source/kernel/gen_system/SYS_System.h
  185. '''
  186. System specific information / access.
  187. For now, only used for commandline parameters.
  188. One of the available implementations must be linked to the application
  189. that uses this system routines.
  190. Please note that this protocol/interface is just for testing,
  191. it needs discussion in the development group for a more final version.
  192. '''
  193. #SYS_GetSystem  = external('SYS_GetSystem' )
  194.  
  195. # blender/source/kernel/gen_messaging/GEN_messaging.h
  196. GEN_init_messaging_system  = external('GEN_init_messaging_system' )
  197.  
  198. # blender/source/blender/blenlib/BLI_args.h
  199. bArgs   = rffi.CStructPtr('bArgs')
  200. #struct bArgs *BLI_argsInit(int argc, char **argv);
  201. BLI_argsInit  = external('BLI_argsInit', [rffi.INT, rffi.CCHARPP ],     bArgs )
  202. #void BLI_argsParse(struct bArgs *ba, int pass, BA_ArgCallback default_cb, void *data);
  203. BLI_argsParse  = external('BLI_argsParse', [ bArgs, rffi.INT, rffi.VOIDP, rffi.VOIDP ] )
  204.  
  205. # blender/source/blender/windowmanager/WM_api.h
  206. '''
  207. void        WM_setprefsize      (int stax, int stay, int sizx, int sizy);
  208. void        WM_setinitialstate_fullscreen();
  209. void        WM_setinitialstate_normal();
  210. void        WM_init             (struct bContext *C, int argc, char **argv);
  211. void        WM_exit             (struct bContext *C);
  212. void        WM_main             (struct bContext *C);
  213. int         WM_init_game        (struct bContext *C);
  214. void        WM_init_splash      (struct bContext *C);
  215. void        WM_check            (struct bContext *C);
  216. '''
  217.  
  218. WM_init  = external('WM_init', [ bContext, rffi.INT, rffi.CCHARPP ] )
  219. WM_main  = external('WM_main', [ bContext ] )
  220.  
  221.  
  222. def mainx( argc, argv ):
  223.     C = CTX_create()        # bContext pointer
  224.     #try:       # binreloc is not important?
  225.     #   br_init  = cfunc('br_init', c_void_p, ('BrInitError', c_void_p,1) )
  226.     #   br_init()
  227.     #except: print 'built without bin-reloc'
  228.     ## setCallbacks not defined header, not important?
  229.     ## only for:    MEM_set_error_callback(mem_error_cb); BLI_setErrorCallBack(error_cb)
  230.     #setCallbacks  = cfunc('setCallbacks', c_void_p )
  231.     #setCallbacks()
  232.  
  233.     BLI_threadapi_init()
  234.     RNA_init()
  235.     RE_engines_init()
  236.     IMB_init()
  237.  
  238.     #syshandle = SYS_GetSystem()        # not final, only for parsing some command lines
  239.     GEN_init_messaging_system()
  240.  
  241.     ba = BLI_argsInit( argc, argv )
  242.     voidp = lltype.nullptr(rffi.VOIDP.TO)
  243.     BLI_argsParse(ba, 1, voidp, voidp )
  244.  
  245.     WM_init( C, argc, argv )        # seg faults
  246.     #BLI_argsInit  = cfunc('BLI_argsInit', c_void_p, ('argc', c_int, 1), ('argv', c_char_p, 1)  )
  247.  
  248.     print 'main exit'
  249.  
  250. def entrypoint( args ):
  251.     print args
  252.     #argv = []
  253.     #for arg in args.split(' '): argv.append( arg )
  254.     #argc = len(argv)
  255.     argv = lltype.malloc(rffi.CCHARPP.TO, 1, flavor='raw')
  256.     argc = 1
  257.     mainx( argc, argv )
  258.     return 0
  259.  
  260.  
  261. if __name__ == '__main__' and 0:
  262.     from pypy.translator.interactive import Translation
  263.     t = Translation( test )
  264.     t.annotate([str]); t.rtype()
  265.     entrypoint = t.compile_c()
  266.     entrypoint(1)
  267.  
  268. def jitpolicy(driver):
  269.     from pypy.module.pypyjit.policy import PyPyJitPolicy
  270.     return PyPyJitPolicy()
  271.  
  272. #pypy-trunk/pypy/translator/goal/translate.py <thisfile.py>
  273. def target(*args):
  274.     return entrypoint, None
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement