1 USING: alien alien.libraries arrays assocs byte-arrays
2 hashtables init kernel math math.parser namespaces python.errors
3 python.ffi python.objects sequences strings vectors ;
7 ERROR: python-error type message traceback ;
9 ! Initialization and finalization
10 : py-initialize ( -- )
11 Py_IsInitialized [ Py_Initialize ] unless ;
14 Py_IsInitialized [ Py_Finalize ] when ;
17 : py-import ( modulename -- module )
18 PyImport_ImportModule check-new-ref ;
20 : py-import-from ( modulename objname -- obj )
21 [ py-import ] [ getattr ] bi* ;
23 ! Data marshalling to Python
24 : array>py-tuple ( array -- py-tuple )
25 [ length <py-tuple> ] keep
26 [ [ dup ] 2dip swap py-tuple-set-item ] each-index ;
28 : vector>py-list ( vector -- py-list )
29 [ length <py-list> ] keep
30 [ [ dup ] 2dip swap py-list-set-item ] each-index ;
32 : assoc>py-dict ( assoc -- py-dict )
33 <py-dict> swap [ [ dup ] 2dip py-dict-set-item ] assoc-each ;
35 : py-tuple>array ( py-tuple -- arr )
36 dup py-tuple-size <iota> [ py-tuple-get-item ] with map ;
38 : py-list>vector ( py-list -- vector )
39 dup py-list-size <iota> [ py-list-get-item ] with V{ } map-as ;
41 : py-unicode>string ( py-unicode -- string )
42 PyUnicode_AsUTF8 (check-ref) ;
44 : py-bytes>byte-array ( py-bytes -- byte-array )
45 PyBytes_AsString (check-ref) >byte-array ;
47 : py-dict>hashtable ( py-dict -- hashtable )
48 PyDict_Items (check-ref) py-list>vector
49 [ py-tuple>array ] map >hashtable ;
51 : py-class-name ( py-object -- name )
52 "__class__" getattr "__name__" getattr py-unicode>string ;
54 GENERIC: >py ( obj -- py-obj )
57 dup length PyBytes_FromStringAndSize check-new-ref ;
60 PyUnicode_FromString check-new-ref ;
63 PyLong_FromLong check-new-ref ;
66 number>string f 10 PyLong_FromString check-new-ref ;
69 PyFloat_FromDouble check-new-ref ;
72 [ >py ] map array>py-tuple ;
75 [ [ >py ] bi@ ] assoc-map assoc>py-dict ;
78 [ >py ] map vector>py-list ;
83 ! Data marshalling to Factor
84 SYMBOL: py-type-dispatch
88 : init-py-type-dispatch ( -- table )
90 { "NoneType" [ drop f ] }
91 { "bool" [ PyObject_IsTrue 1 = ] }
92 { "bytes" [ py-bytes>byte-array ] }
93 { "dict" [ py-dict>hashtable [ [ py> ] bi@ ] assoc-map ] }
94 { "int" [ PyLong_AsLong ] }
95 { "list" [ py-list>vector [ py> ] map ] }
96 { "str" [ py-unicode>string ] }
97 { "tuple" [ py-tuple>array [ py> ] map ] }
100 py-type-dispatch [ init-py-type-dispatch ] initialize
102 ERROR: missing-type type ;
104 : py> ( py-obj -- obj )
105 dup py-class-name py-type-dispatch get ?at
106 [ call( x -- x ) ] [ missing-type ] if ;
109 : quot>py-callback ( quot: ( args kw -- ret ) -- alien )
110 '[ nipd [ [ py> ] [ { } ] if* ] bi@ @ >py ] PyCallback ; inline
112 : with-quot>py-cfunction ( alien quot -- )
113 '[ <py-cfunction> @ ] with-callback ; inline
115 : python-dll-loaded? ( -- ? )
116 "Py_IsInitialized" "python" dlsym? ;
118 STARTUP-HOOK: [ python-dll-loaded? [ py-initialize ] when ]
119 SHUTDOWN-HOOK: [ python-dll-loaded? [ py-finalize ] when ]