code.putln(" #ifndef __cdecl")
code.putln(" #define __cdecl")
code.putln(" #endif")
+ code.putln(" #ifndef __fastcall")
+ code.putln(" #define __fastcall")
+ code.putln(" #endif")
code.putln("#else")
code.putln(" #define _USE_MATH_DEFINES")
code.putln("#endif")
nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
if self.optional_arg_count:
func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
+ callspec = env.directives['callspec']
+ if callspec:
+ current = func_type.calling_convention
+ if current and current != callspec:
+ error(self.pos, "cannot have both '%s' and '%s' "
+ "calling conventions" % (current, callspec))
+ func_type.calling_convention = callspec
return self.base.analyse(func_type, env)
'always_allow_keywords': False,
'wraparound' : True,
'c99_complex' : False, # Don't use macro wrappers for complex arith, not sure what to name this...
+ 'callspec' : "",
}
# Override types possibilities above, if needed
raise PostParseError(dec.function.pos,
'The %s option takes one compile-time boolean argument' % optname)
return (optname, args[0].value)
+ elif optiontype is str:
+ if kwds is not None or len(args) != 1 or not isinstance(args[0], StringNode):
+ raise PostParseError(dec.function.pos,
+ 'The %s option takes one compile-time string argument' % optname)
+ return (optname, args[0].value)
elif optiontype is dict:
if len(args) != 0:
raise PostParseError(dec.function.pos,
else:
return ""
-calling_convention_words = ("__stdcall", "__cdecl")
+calling_convention_words = ("__stdcall", "__cdecl", "__fastcall")
def p_c_complex_base_type(s):
# s.sy == '('
return 1
def same_calling_convention_as(self, other):
+ ## XXX Under discussion ...
+ ## callspec_words = ("__stdcall", "__cdecl", "__fastcall")
+ ## cs1 = self.calling_convention
+ ## cs2 = other.calling_convention
+ ## if (cs1 in callspec_words or
+ ## cs2 in callspec_words):
+ ## return cs1 == cs2
+ ## else:
+ ## return True
sc1 = self.calling_convention == '__stdcall'
sc2 = other.calling_convention == '__stdcall'
return sc1 == sc2
-cdef extern int f()
+cdef extern int f1()
-cdef extern int __stdcall g()
+cdef extern int __cdecl f2()
-cdef extern int __cdecl h()
+cdef extern int __stdcall f3()
-cdef extern int (__stdcall *p)()
+cdef extern int __fastcall f4()
+
+
+cdef extern int (*p1)()
+
+cdef extern int (__cdecl *p2)()
+
+cdef extern int (__stdcall *p3)()
+
+cdef extern int (__fastcall *p4)()
+
+
+p1 = f1
+p2 = f2
+p3 = f3
+p4 = f4
--- /dev/null
+cimport cython
+
+@cython.callspec("")
+cdef void h1(): pass
+
+@cython.callspec("__cdecl")
+cdef void __cdecl h2(): pass
+
+@cython.callspec("__stdcall")
+cdef void __stdcall h3(): pass
+
+@cython.callspec("__fastcall")
+cdef void __fastcall h4(): pass
+
+@cython.callspec("__cdecl")
+cdef void __stdcall h5(): pass # fail
+
+@cython.callspec("__cdecl")
+cdef void __fastcall h6(): pass # fail
+
+cdef void (*p1)()
+cdef void (__cdecl *p2)()
+cdef void (__stdcall *p3)()
+cdef void (__fastcall *p4)()
+
+p1 = h1
+p2 = h2
+p3 = h3
+p4 = h4
+
+#p1 = h2 # fail
+#p1 = h3 # fail
+#p1 = h4 # fail
+
+#p2 = h1 # fail
+#p2 = h3 # fail
+#p2 = h4 # fail
+
+_ERRORS = u"""
+16:22: cannot have both '__stdcall' and '__cdecl' calling conventions
+19:23: cannot have both '__fastcall' and '__cdecl' calling conventions
+"""
+#31:14: Cannot assign type 'void (__cdecl )(void)' to 'void (*)(void)'
+#32:14: Cannot assign type 'void (__stdcall )(void)' to 'void (*)(void)'
+#33:14: Cannot assign type 'void (__fastcall )(void)' to 'void (*)(void)'
+#35:14: Cannot assign type 'void (void)' to 'void (__cdecl *)(void)'
+#36:14: Cannot assign type 'void (__stdcall )(void)' to 'void (__cdecl *)(void)'
+#37:14: Cannot assign type 'void (__fastcall )(void)' to 'void (__cdecl *)(void)'