arg_code = actual_arg.result_as(formal_arg.type)
arg_list_code.append(arg_code)
+ if func_type.is_overridable:
+ arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
+
if func_type.optional_arg_count:
if expected_nargs == actual_nargs:
optional_args = 'NULL'
arg_list_code.append(actual_arg.result_code)
result = "%s(%s)" % (self.function.result_code,
join(arg_list_code, ", "))
- if self.wrapper_call or \
- self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
- result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
+# if self.wrapper_call or \
+# self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
+# result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
return result
def generate_result_code(self, code):
cleanup_cname = pyrex_prefix + "module_cleanup"
pymoduledef_cname = pyrex_prefix + "moduledef"
optional_args_cname = pyrex_prefix + "optional_args"
-no_opt_args = pyrex_prefix + "no_opt_args"
import_star = pyrex_prefix + "import_star"
import_star_set = pyrex_prefix + "import_star_set"
cur_scope_cname = pyrex_prefix + "cur_scope"
code.exit_cfunc_scope()
if self.py_func:
self.py_func.generate_function_definitions(env, code)
- self.generate_optarg_wrapper_function(env, code)
+ self.generate_wrapper_functions(code)
def declare_argument(self, env, arg):
if arg.type.is_void:
error(arg.pos,
"Argument type '%s' is incomplete" % arg.type)
return env.declare_arg(arg.name, arg.type, arg.pos)
- def generate_optarg_wrapper_function(self, env, code):
+
+ def generate_wrapper_functions(self, code):
pass
def generate_execution_code(self, code):
# with_gil boolean Acquire GIL around body
# type CFuncType
# py_func wrapper for calling from Python
+ # overridable whether or not this is a cpdef function
child_attrs = ["base_type", "declarator", "body", "py_func"]
if self.overridable:
self.py_func.analyse_expressions(env)
- def generate_function_header(self, code, with_pymethdef, with_opt_args = 1):
+ def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
arg_decls = []
type = self.type
visibility = self.entry.visibility
for arg in type.args[:len(type.args)-type.optional_arg_count]:
arg_decls.append(arg.declaration_code())
+ if with_dispatch and self.overridable:
+ arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
if type.optional_arg_count and with_opt_args:
arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
if type.has_varargs:
arg_decls.append("...")
if not arg_decls:
arg_decls = ["void"]
- cname = self.entry.func_cname
- if not with_opt_args:
- cname += Naming.no_opt_args
+ if cname is None:
+ cname = self.entry.func_cname
entity = type.function_header_code(cname, string.join(arg_decls, ", "))
if visibility == 'public':
dll_linkage = "DL_EXPORT"
def caller_will_check_exceptions(self):
return self.entry.type.exception_check
-
- def generate_optarg_wrapper_function(self, env, code):
- if self.type.optional_arg_count and \
- self.type.original_sig and not self.type.original_sig.optional_arg_count:
+
+ def generate_wrapper_functions(self, code):
+ # If the C signature of a function has changed, we need to generate
+ # wrappers to put in the slots here.
+ k = 0
+ entry = self.entry
+ func_type = entry.type
+ while entry.prev_entry is not None:
+ k += 1
+ entry = entry.prev_entry
+ entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
code.putln()
- self.generate_function_header(code, 0, with_opt_args = 0)
+ self.generate_function_header(code,
+ 0,
+ with_dispatch = entry.type.is_overridable,
+ with_opt_args = entry.type.optional_arg_count,
+ cname = entry.func_cname)
if not self.return_type.is_void:
code.put('return ')
args = self.type.args
arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
- arglist.append('NULL')
+ if entry.type.is_overridable:
+ arglist.append(Naming.skip_dispatch_cname)
+ elif func_type.is_overridable:
+ arglist.append('0')
+ if entry.type.optional_arg_count:
+ arglist.append(Naming.optional_args_cname)
+ elif func_type.optional_arg_count:
+ arglist.append('NULL')
code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
code.putln('}')
-
+
class PyArgDeclNode(Node):
# Argument which must be a Python object (used
else:
self_arg = "((PyObject *)%s)" % self.args[0].cname
code.putln("/* Check if called by wrapper */")
- code.putln("if (unlikely(%s)) %s = 0;" % (Naming.skip_dispatch_cname, Naming.skip_dispatch_cname))
+ code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
code.putln("/* Check if overriden in Python */")
if self.py_func.is_module_scope:
code.putln("else {")
return 1
if not other_type.is_cfunction:
return 0
- if not self.is_overridable and other_type.is_overridable:
+ if self.is_overridable != other_type.is_overridable:
return 0
nargs = len(self.args)
if nargs != len(other_type.args):
for arg in self.args[:len(self.args)-self.optional_arg_count]:
arg_decl_list.append(
arg.type.declaration_code("", for_display, pyrex = pyrex))
+ if self.is_overridable:
+ arg_decl_list.append("int %s" % Naming.skip_dispatch_cname)
if self.optional_arg_count:
arg_decl_list.append(self.op_arg_struct.declaration_code(Naming.optional_args_cname))
if self.has_varargs:
utility_code = None
is_overridable = 0
buffer_aux = None
+ prev_entry = None
def __init__(self, name, cname, type, pos = None, init = None):
self.name = name
if name and dict.has_key(name):
if visibility == 'extern':
warning(pos, "'%s' redeclared " % name, 0)
- else:
+ elif visibility != 'ignore':
error(pos, "'%s' redeclared " % name)
entry = Entry(name, cname, type, pos = pos)
entry.in_cinclude = self.in_cinclude
if type.same_c_signature_as(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
pass
elif type.compatible_signature_with(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
- if type.optional_arg_count and not type.original_sig.optional_arg_count:
- # Need to put a wrapper taking no optional arguments
- # into the method table.
- wrapper_func_cname = self.mangle(Naming.func_prefix, name) + Naming.no_opt_args
- wrapper_func_name = name + Naming.no_opt_args
- if entry.type.optional_arg_count:
- old_entry = self.lookup_here(wrapper_func_name)
- old_entry.func_cname = wrapper_func_cname
- else:
- entry.func_cname = wrapper_func_cname
- entry.name = wrapper_func_name
- entry = self.add_cfunction(name, type, pos, cname or name, visibility)
- defining = 1
- entry.type = type
-# if type.narrower_c_signature_than(entry.type, as_cmethod = 1):
-# entry.type = type
+ entry = self.add_cfunction(name, type, pos, cname or name, visibility='ignore')
+ defining = 1
else:
error(pos, "Signature not compatible with previous declaration")
error(entry.pos, "Previous declaration is here")
def add_cfunction(self, name, type, pos, cname, visibility):
# Add a cfunction entry without giving it a func_cname.
+ prev_entry = self.lookup_here(name)
entry = ClassScope.add_cfunction(self, name, type, pos, cname, visibility)
entry.is_cmethod = 1
+ entry.prev_entry = prev_entry
return entry
def declare_property(self, name, doc, pos):