1313# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1414
1515from raylib import rl , ffi
16-
1716from inspect import ismethod ,getmembers ,isbuiltin
1817import inflection
1918
@@ -60,31 +59,60 @@ def pointer(self, struct):
6059# Another possibility is ffi.typeof() but that will throw an exception if you give it a type that isn't a ctype
6160# Another way to improve performance might be to special-case simple types before doing the string comparisons
6261
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 ):
6480 #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
65104 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 :
78110 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+
85113 return func
86114
87- def makeStructHelper (struct ):
115+ def makeStruct (struct ):
88116 def func (* args ):
89117 return ffi .new (f"struct { struct } *" , args )[0 ]
90118 return func
@@ -99,7 +127,7 @@ def func(*args):
99127 #print(attr.__text_signature__)
100128 #print(dir(attr))
101129 #print(dir(attr.__repr__))
102- f = makefunc (attr )
130+ f = makeFunc (attr )
103131 setattr (current_module , uname , f )
104132 #def wrap(*args):
105133 # print("call to ",attr)
@@ -108,6 +136,5 @@ def func(*args):
108136 setattr (current_module , name , attr )
109137
110138for struct in ffi .list_types ()[0 ]:
111- f = makeStructHelper (struct )
139+ f = makeStruct (struct )
112140 setattr (current_module , struct , f )
113-
0 commit comments