@@ -38,37 +38,28 @@ def _underscore(word: str) -> str:
38
38
return word .lower ()
39
39
40
40
41
- def pointer (struct ):
42
- return ffi .addressof (struct )
43
-
44
-
45
- # I'm concerned that we are doing a lot of string comparisons on every function call to detect types.
46
- # Quickest way would probably be isinstance(result, ffi._backend._CDataBase) but that class name varies
47
- # depending on if binding is static/dynamic
48
- # (and possibly also different on pypy implementations?).
49
- # which makes me reluctant to rely on it.
50
- # Another possibility is ffi.typeof() but that will throw an exception if you give it a type that isn't a ctype
51
- # Another way to improve performance might be to special-case simple types before doing the string comparisons
52
-
53
41
def _wrap_function (original_func ):
54
42
c_args = [str (x ) for x in ffi .typeof (original_func ).args ]
55
- number_of_args = len (c_args )
43
+ number_of_args = len (c_args )
56
44
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 ]
58
- # print("makefunc ",a, ffi.typeof(a).args)
45
+ c_arg_is_string = [str (x ) == "<ctype 'char *'>" for x in ffi .typeof (original_func ).args ]
46
+ # c_arg_is_void_pointer = [str(x) == "<ctype 'void *'>" for x in ffi.typeof(original_func).args]
47
+
59
48
def wrapped_func (* args ):
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 ):
49
+ args = list (args ) # tuple is immutable, converting it to mutable list is faster than constructing new list!
50
+ for i in range (number_of_args ):
62
51
try :
63
- arg = args [i ]
52
+ arg = args [i ]
64
53
except IndexError :
65
54
raise RuntimeError (f"function requires { number_of_args } arguments but you supplied { len (args )} " )
66
55
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
56
+ if c_arg_is_string [i ]: # we assume c_arg is 'const char *'
57
+ try : # if it's a non-const 'char *' then user should be supplying a ctype pointer, not a Python
58
+ # string
59
+ args [i ] = arg .encode ('utf-8' ) # in that case this conversion will fail
60
+ except AttributeError : # but those functions are uncommon, so quicker on average to try the
61
+ # conversion
62
+ pass # and ignore the exception
72
63
# if user supplied a Python string but c_arg is a 'char *' not a 'const char *' then we ought to raise
73
64
# exception because its an out
74
65
# parameter and user should supply a ctype pointer, but we cant because cffi cant detect 'const'
@@ -82,13 +73,24 @@ def wrapped_func(*args):
82
73
elif not is_cdata (arg ):
83
74
if c_args [i ] == "<ctype '_Bool *'>" :
84
75
raise TypeError (
85
- "Argument must be a ctype bool, please create one with: pyray.ffi.new('bool *', True)" )
76
+ f"Argument { i } ({ arg } ) must be a ctype bool, please create one with: pyray.ffi.new('bool "
77
+ f"*', True)" )
86
78
elif c_args [i ] == "<ctype 'int *'>" :
87
79
raise TypeError (
88
- "Argument must be a ctype int, please create one with: pyray.ffi.new('int *', 1)" )
80
+ f"Argument { i } ({ arg } ) must be a ctype int, please create one with: pyray.ffi.new('int "
81
+ f"*', 1)" )
89
82
elif c_args [i ] == "<ctype 'float *'>" :
90
83
raise TypeError (
91
- "Argument must be a ctype float, please create one with: pyray.ffi.new('float *', 1.0)" )
84
+ f"Argument { i } ({ arg } ) must be a ctype float, please create one with: pyray.ffi.new("
85
+ f"'float *', 1.0)" )
86
+ elif c_args [i ] == "<ctype 'void *'>" :
87
+ # we could assume it's a string and try to convert it but we would have to be sure it's
88
+ # const. that seems reasonable assumption for char* but i'm not confident it is for void*
89
+ raise TypeError (
90
+ f"Argument { i } ({ arg } ) must be a cdata pointer. Type is void so I don't know what type it "
91
+ f"should be."
92
+ "If it's a const string you can create it with pyray.ffi.new('char []', b\" whatever\" ) . "
93
+ "If it's a float you can create it with pyray.ffi.new('float *', 1.0)" )
92
94
93
95
result = original_func (* args )
94
96
if result is None :
@@ -152,3 +154,7 @@ def func(*args):
152
154
153
155
# overwrite ffi enums with our own
154
156
from raylib .enums import *
157
+
158
+
159
+ def text_format (* args ):
160
+ raise RuntimeError ("Use Python f-strings etc rather than calling text_format()." )
0 commit comments