@@ -51,35 +51,46 @@ def pointer(struct):
51
51
# Another way to improve performance might be to special-case simple types before doing the string comparisons
52
52
53
53
def _wrap_function (original_func ):
54
+ c_args = [str (x ) for x in ffi .typeof (original_func ).args ]
55
+ number_of_args = len (c_args )
56
+ c_arg_is_pointer = [x .kind == 'pointer' for x in ffi .typeof (original_func ).args ]
57
+ c_arg_is_string = [str (x ) == "<ctype 'char *'>" for x in ffi .typeof (original_func ).args ]
54
58
# print("makefunc ",a, ffi.typeof(a).args)
55
59
def wrapped_func (* args ):
56
- modified_args = []
57
- for (c_arg , arg ) in zip (ffi .typeof (original_func ).args , args ):
58
- # print("arg:",str(arg), "c_arg.kind:", c_arg.kind, "c_arg:", c_arg, "type(arg):",str(type(arg)))
59
- if c_arg .kind == 'pointer' :
60
- if type (arg ) is str :
61
- arg = arg .encode ('utf-8' )
62
- # if c_arg is a 'char *' not a 'const char *' then we ought to raise here because its an out
63
- # parameter and user should supply a ctype pointer, but cffi cant detect const
60
+ args = list (args ) # tuple is immutable, converting it to mutable list is faster than constructing new list!
61
+ for i in range (0 , number_of_args ):
62
+ try :
63
+ arg = args [i ]
64
+ except IndexError :
65
+ raise RuntimeError (f"function requires { number_of_args } arguments but you supplied { len (args )} " )
66
+ if c_arg_is_pointer [i ]:
67
+ if c_arg_is_string [i ]: # we assume c_arg is 'const char *'
68
+ try : # if it's a 'char *' then user should be supplying a ctype pointer, not a Python string
69
+ args [i ] = arg .encode ('utf-8' ) # in that case this conversion will fail
70
+ except AttributeError : # but those functions are uncommon, so quicker on average to try the conversion
71
+ pass # and ignore the exception
72
+ # if user supplied a Python string but c_arg is a 'char *' not a 'const char *' then we ought to raise
73
+ # exception because its an out
74
+ # parameter and user should supply a ctype pointer, but we cant because cffi cant detect 'const'
64
75
# so we would have to get the info from raylib.json
65
- elif type ( arg ) is list and str ( c_arg ) == "<ctype 'char * *'>" :
66
- arg = [ffi .new ("char[]" , x .encode ('utf-8' )) for x in arg ]
76
+ elif c_args [ i ] == "<ctype 'char * *'>" and type ( arg ) is list :
77
+ args [ i ] = [ffi .new ("char[]" , x .encode ('utf-8' )) for x in arg ]
67
78
elif is_cdata (arg ) and "*" not in str (arg ):
68
- arg = ffi .addressof (arg )
79
+ args [ i ] = ffi .addressof (arg )
69
80
elif arg is None :
70
- arg = ffi .NULL
81
+ args [ i ] = ffi .NULL
71
82
elif not is_cdata (arg ):
72
- if str ( c_arg ) == "<ctype '_Bool *'>" :
83
+ if c_args [ i ] == "<ctype '_Bool *'>" :
73
84
raise TypeError (
74
85
"Argument must be a ctype bool, please create one with: pyray.ffi.new('bool *', True)" )
75
- elif str ( c_arg ) == "<ctype 'int *'>" :
86
+ elif c_args [ i ] == "<ctype 'int *'>" :
76
87
raise TypeError (
77
88
"Argument must be a ctype int, please create one with: pyray.ffi.new('int *', 1)" )
78
- elif str ( c_arg ) == "<ctype 'float *'>" :
89
+ elif c_args [ i ] == "<ctype 'float *'>" :
79
90
raise TypeError (
80
91
"Argument must be a ctype float, please create one with: pyray.ffi.new('float *', 1.0)" )
81
- modified_args . append ( arg )
82
- result = original_func (* modified_args )
92
+
93
+ result = original_func (* args )
83
94
if result is None :
84
95
return
85
96
elif is_cdata (result ) and str (result ).startswith ("<cdata 'char *'" ):
0 commit comments