Commit 54961a30 authored by Stefan Behnel's avatar Stefan Behnel

simplify also return type conversion in cfunc wrapper

parent e69df685
...@@ -2662,10 +2662,9 @@ class CFuncType(CType): ...@@ -2662,10 +2662,9 @@ class CFuncType(CType):
if arg.type.is_extension_type: if arg.type.is_extension_type:
env.use_utility_code(UtilityCode.load_cached("ExtTypeTest", "ObjectHandling.c")) env.use_utility_code(UtilityCode.load_cached("ExtTypeTest", "ObjectHandling.c"))
def declared_type(ix, ctype): def declared_type(ctype, type_name):
py_arg_type = '' py_arg_type = ''
type_convert = '' type_convert = ''
type_name = 'TYPE%s' % ix
type_cname = ctype.declaration_code("") type_cname = ctype.declaration_code("")
type_displayname = str(ctype.declaration_code("", for_display=True)) type_displayname = str(ctype.declaration_code("", for_display=True))
if ctype.is_builtin_type: if ctype.is_builtin_type:
...@@ -2674,6 +2673,8 @@ class CFuncType(CType): ...@@ -2674,6 +2673,8 @@ class CFuncType(CType):
type_convert = '<%s>' % type_name type_convert = '<%s>' % type_name
elif ctype.is_pyobject: elif ctype.is_pyobject:
type_convert = '' type_convert = ''
elif ctype is c_bint_type:
type_name = py_arg_type = 'bint'
elif ctype.is_typedef or ctype.is_struct_or_union: elif ctype.is_typedef or ctype.is_struct_or_union:
type_convert = '%s_to_py' % type_name type_convert = '%s_to_py' % type_name
else: else:
...@@ -2686,7 +2687,7 @@ class CFuncType(CType): ...@@ -2686,7 +2687,7 @@ class CFuncType(CType):
self.name = arg.name or 'ARG%s' % ix self.name = arg.name or 'ARG%s' % ix
self.type = arg.type self.type = arg.type
self.type_name, self.type_cname, self.py_arg_type, self.type_displayname, self.type_convert = ( self.type_name, self.type_cname, self.py_arg_type, self.type_displayname, self.type_convert = (
declared_type(ix, self.type)) declared_type(self.type, 'TYPE%s' % ix))
def declare_type_def(self): def declare_type_def(self):
if self.type.is_extension_type or (not self.type.is_pyobject and not self.py_arg_type): if self.type.is_extension_type or (not self.type.is_pyobject and not self.py_arg_type):
...@@ -2709,9 +2710,12 @@ class CFuncType(CType): ...@@ -2709,9 +2710,12 @@ class CFuncType(CType):
return_type = 'void' return_type = 'void'
declare_return_type = '' declare_return_type = ''
declare_return_type_convert = '' declare_return_type_convert = ''
return_type_displayname = ''
maybe_return = '' maybe_return = ''
except_clause = 'except *' except_clause = 'except *'
else: else:
return_type, return_type_cname, return_arg_type, return_type_displayname, _ = (
declared_type(self.return_type, 'RETURN_TYPE'))
if self.return_type.is_pyobject: if self.return_type.is_pyobject:
to_py = '(PyObject*)' to_py = '(PyObject*)'
except_clause = '' except_clause = ''
...@@ -2720,15 +2724,21 @@ class CFuncType(CType): ...@@ -2720,15 +2724,21 @@ class CFuncType(CType):
return False return False
to_py = self.return_type.to_py_function to_py = self.return_type.to_py_function
except_clause = 'except *' except_clause = 'except *'
return_type = 'RETURN_TYPE' if return_arg_type:
declare_return_type = 'ctypedef void* RETURN_TYPE "%s"' % self.return_type.declaration_code('') return_type = return_arg_type
declare_return_type_convert = 'cdef object RETURN_TYPE_from_py "%s" (RETURN_TYPE)' % to_py declare_return_type = ''
maybe_return = 'return RETURN_TYPE_from_py' declare_return_type_convert = ''
maybe_return = 'return '
else:
declare_return_type = 'ctypedef void* RETURN_TYPE "%s"' % return_type_cname
declare_return_type_convert = 'cdef object RETURN_TYPE_from_py "%s" (RETURN_TYPE)' % to_py
maybe_return = 'return RETURN_TYPE_from_py'
context = { context = {
'cname': self.to_py_function, 'cname': self.to_py_function,
'args': [Arg(ix, arg) for ix, arg in enumerate(self.args)], 'args': [Arg(ix, arg) for ix, arg in enumerate(self.args)],
'return_type': return_type, 'return_type': return_type,
'return_type_displayname': return_type_displayname,
'declare_return_type': declare_return_type, 'declare_return_type': declare_return_type,
'declare_return_type_convert': declare_return_type_convert, 'declare_return_type_convert': declare_return_type_convert,
'maybe_return': maybe_return, 'maybe_return': maybe_return,
......
...@@ -14,7 +14,7 @@ cdef extern from *: ...@@ -14,7 +14,7 @@ cdef extern from *:
@cname("{{cname}}") @cname("{{cname}}")
cdef object {{cname}}({{return_type}} (*f)({{ ', '.join(arg.type_name for arg in args) }}) {{except_clause}}): cdef object {{cname}}({{return_type}} (*f)({{ ', '.join(arg.type_name for arg in args) }}) {{except_clause}}):
def wrap({{ ', '.join('{arg.py_arg_type} {arg.name}'.format(arg=arg) for arg in args) }}): def wrap({{ ', '.join('{arg.py_arg_type} {arg.name}'.format(arg=arg) for arg in args) }}):
"""wrap({{', '.join('{arg.name}: {arg.type_displayname!r}'.format(arg=arg) for arg in args)}})""" """wrap({{', '.join('{arg.name}: {arg.type_displayname!r}'.format(arg=arg) for arg in args)}}){{if return_type_displayname}} -> {{repr(return_type_displayname)}}{{endif}}"""
{{for arg in args}} {{for arg in args}}
{{arg.check_type()}} {{arg.check_type()}}
{{endfor}} {{endfor}}
......
...@@ -38,7 +38,7 @@ def return_square_c(): ...@@ -38,7 +38,7 @@ def return_square_c():
>>> square_c(x=4) >>> square_c(x=4)
16.0 16.0
>>> square_c.__doc__ # FIXME: try to make original C function name available >>> square_c.__doc__ # FIXME: try to make original C function name available
"wrap(x: 'double')" "wrap(x: 'double') -> 'double'"
""" """
return square_c return square_c
...@@ -50,6 +50,8 @@ def return_libc_sqrt(): ...@@ -50,6 +50,8 @@ def return_libc_sqrt():
3.0 3.0
>>> sqrt(x=9) >>> sqrt(x=9)
3.0 3.0
>>> sqrt.__doc__
"wrap(x: 'double') -> 'double'"
""" """
return sqrt return sqrt
...@@ -94,7 +96,7 @@ def return_abc(): ...@@ -94,7 +96,7 @@ def return_abc():
>>> abc(2, 3, 5) >>> abc(2, 3, 5)
False False
>>> abc.__doc__ >>> abc.__doc__
"wrap(a: 'long long', b: 'long long', c: 'long long')" "wrap(a: 'long long', b: 'long long', c: 'long long') -> 'bool'"
""" """
return abc return abc
...@@ -111,6 +113,42 @@ def test_typedef(x): ...@@ -111,6 +113,42 @@ def test_typedef(x):
return (<object>test_typedef_cfunc)(x) return (<object>test_typedef_cfunc)(x)
cdef union my_union:
int a
double b
cdef struct my_struct:
int which
my_union y
cdef my_struct c_struct_builder(int which, int a, double b):
cdef my_struct value
value.which = which
if which:
value.y.a = a
else:
value.y.b = b
return value
def return_struct_builder():
"""
>>> make = return_struct_builder()
>>> d = make(0, 1, 2)
>>> d['which']
0
>>> d['y']['b']
2.0
>>> d = make(1, 1, 2)
>>> d['which']
1
>>> d['y']['a']
1
>>> make.__doc__
"wrap(which: 'int', a: 'int', b: 'double') -> 'my_struct'"
"""
return c_struct_builder
cdef object test_object_params_cfunc(a, b): cdef object test_object_params_cfunc(a, b):
return a, b return a, b
...@@ -132,7 +170,7 @@ def test_builtin_params(a, b): ...@@ -132,7 +170,7 @@ def test_builtin_params(a, b):
>>> test_builtin_params(1, 2) >>> test_builtin_params(1, 2)
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: Cannot convert int to list TypeError: Argument 'a' has incorrect type (expected list, got int)
""" """
return (<object>test_builtin_params_cfunc)(a, b) return (<object>test_builtin_params_cfunc)(a, b)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment