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):
if arg.type.is_extension_type:
env.use_utility_code(UtilityCode.load_cached("ExtTypeTest", "ObjectHandling.c"))
def declared_type(ix, ctype):
def declared_type(ctype, type_name):
py_arg_type = ''
type_convert = ''
type_name = 'TYPE%s' % ix
type_cname = ctype.declaration_code("")
type_displayname = str(ctype.declaration_code("", for_display=True))
if ctype.is_builtin_type:
......@@ -2674,6 +2673,8 @@ class CFuncType(CType):
type_convert = '<%s>' % type_name
elif ctype.is_pyobject:
type_convert = ''
elif ctype is c_bint_type:
type_name = py_arg_type = 'bint'
elif ctype.is_typedef or ctype.is_struct_or_union:
type_convert = '%s_to_py' % type_name
else:
......@@ -2686,7 +2687,7 @@ class CFuncType(CType):
self.name = arg.name or 'ARG%s' % ix
self.type = arg.type
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):
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):
return_type = 'void'
declare_return_type = ''
declare_return_type_convert = ''
return_type_displayname = ''
maybe_return = ''
except_clause = 'except *'
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:
to_py = '(PyObject*)'
except_clause = ''
......@@ -2720,15 +2724,21 @@ class CFuncType(CType):
return False
to_py = self.return_type.to_py_function
except_clause = 'except *'
return_type = 'RETURN_TYPE'
declare_return_type = 'ctypedef void* RETURN_TYPE "%s"' % self.return_type.declaration_code('')
declare_return_type_convert = 'cdef object RETURN_TYPE_from_py "%s" (RETURN_TYPE)' % to_py
maybe_return = 'return RETURN_TYPE_from_py'
if return_arg_type:
return_type = return_arg_type
declare_return_type = ''
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 = {
'cname': self.to_py_function,
'args': [Arg(ix, arg) for ix, arg in enumerate(self.args)],
'return_type': return_type,
'return_type_displayname': return_type_displayname,
'declare_return_type': declare_return_type,
'declare_return_type_convert': declare_return_type_convert,
'maybe_return': maybe_return,
......
......@@ -14,7 +14,7 @@ cdef extern from *:
@cname("{{cname}}")
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) }}):
"""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}}
{{arg.check_type()}}
{{endfor}}
......
......@@ -38,7 +38,7 @@ def return_square_c():
>>> square_c(x=4)
16.0
>>> square_c.__doc__ # FIXME: try to make original C function name available
"wrap(x: 'double')"
"wrap(x: 'double') -> 'double'"
"""
return square_c
......@@ -50,6 +50,8 @@ def return_libc_sqrt():
3.0
>>> sqrt(x=9)
3.0
>>> sqrt.__doc__
"wrap(x: 'double') -> 'double'"
"""
return sqrt
......@@ -94,7 +96,7 @@ def return_abc():
>>> abc(2, 3, 5)
False
>>> 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
......@@ -111,6 +113,42 @@ def test_typedef(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):
return a, b
......@@ -132,7 +170,7 @@ def test_builtin_params(a, b):
>>> test_builtin_params(1, 2)
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)
......
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