13
13
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
14
14
15
15
from raylib import rl , ffi
16
-
17
16
from inspect import ismethod ,getmembers ,isbuiltin
18
17
import inflection
19
18
@@ -60,31 +59,60 @@ def pointer(self, struct):
60
59
# Another possibility is ffi.typeof() but that will throw an exception if you give it a type that isn't a ctype
61
60
# Another way to improve performance might be to special-case simple types before doing the string comparisons
62
61
63
- def makefunc (a ):
62
+ ## simple value converters
63
+ # will fail if fed wrong arguments
64
+
65
+ def as_is (value ):
66
+ return value
67
+
68
+ def to_bytes (value ):
69
+ if type (value ) is bytes : return value
70
+ else : return value .encode ('utf-8' , 'ignore' )
71
+
72
+ def to_str (value ):
73
+ return ffi .string (value ).decode ('utf-8' )
74
+
75
+ def to_pointer (value ):
76
+ return ffi .addressof (value )
77
+
78
+
79
+ def makeFunc (c_func ):
64
80
#print("makefunc ",a, ffi.typeof(a).args)
81
+
82
+ # based on ctypes of arguments of the c function
83
+ # we build a list of converters to call on python function arguments
84
+ converters = []
85
+ for c_arg_type in ffi .typeof (c_func ).args :
86
+ if c_arg_type is ffi .typeof ('char *' ):
87
+ converters .append (to_bytes )
88
+ elif c_arg_type .kind == 'pointer' :
89
+ converters .append (to_pointer )
90
+ else :
91
+ converters .append (as_is )
92
+
93
+ # not sure if this would bring any speedup
94
+ #converters = tuple(converters)
95
+
96
+ resultConverter = None
97
+ c_result_type = ffi .typeof (c_func ).result
98
+ if c_result_type is ffi .typeof ('char *' ):
99
+ resultConverter = to_str
100
+ elif c_result_type :
101
+ resultConverter = as_is
102
+
103
+ # use a closure to bring converters into c function call
65
104
def func (* args ):
66
- modified_args = []
67
- for (c_arg , arg ) in zip (ffi .typeof (a ).args , args ):
68
- #print(arg, c_arg.kind)
69
- if type (arg ) == str :
70
- encoded = arg .encode ('utf-8' )
71
- modified_args .append (encoded )
72
- elif c_arg .kind == 'pointer' and str (type (arg )) == "<class '_cffi_backend.__CDataOwn'>" :
73
- modified_args .append (ffi .addressof (arg ))
74
- else :
75
- modified_args .append (arg )
76
- result = a (* modified_args )
77
- if result is None :
105
+ nonlocal converters , resultConverter
106
+
107
+ result = c_func (* (convert (arg ) for (arg , convert ) in zip (args , converters ) ) )
108
+
109
+ if result is None or resultConverter is None :
78
110
return
79
- if str (type (result )) == "<class '_cffi_backend._CDataBase'>" and str (result ).startswith ("<cdata 'char *'" ):
80
- if str (result ) == "<cdata 'char *' NULL>" :
81
- result = ""
82
- else :
83
- result = ffi .string (result ).decode ('utf-8' )
84
- return result
111
+ return resultConverter (result )
112
+
85
113
return func
86
114
87
- def makeStructHelper (struct ):
115
+ def makeStruct (struct ):
88
116
def func (* args ):
89
117
return ffi .new (f"struct { struct } *" , args )[0 ]
90
118
return func
@@ -99,7 +127,7 @@ def func(*args):
99
127
#print(attr.__text_signature__)
100
128
#print(dir(attr))
101
129
#print(dir(attr.__repr__))
102
- f = makefunc (attr )
130
+ f = makeFunc (attr )
103
131
setattr (current_module , uname , f )
104
132
#def wrap(*args):
105
133
# print("call to ",attr)
@@ -108,6 +136,5 @@ def func(*args):
108
136
setattr (current_module , name , attr )
109
137
110
138
for struct in ffi .list_types ()[0 ]:
111
- f = makeStructHelper (struct )
139
+ f = makeStruct (struct )
112
140
setattr (current_module , struct , f )
113
-
0 commit comments