self.generate_c_code(env, options, result)
self.generate_h_code(env, options, result)
self.generate_api_code(env, result)
-
+
def has_imported_c_functions(self):
for module in self.referenced_modules:
for entry in module.cfunc_entries:
f.close()
def generate_h_code(self, env, options, result):
- def h_entries(entries, pxd = 0):
+ def h_entries(entries, api=0, pxd=0):
return [entry for entry in entries
- if entry.visibility == 'public' or pxd and entry.defined_in_pxd]
- h_types = h_entries(env.type_entries)
+ if ((entry.visibility == 'public') or
+ (api and entry.api) or
+ (pxd and entry.defined_in_pxd))]
+ h_types = h_entries(env.type_entries, api=1)
h_vars = h_entries(env.var_entries)
h_funcs = h_entries(env.cfunc_entries)
h_extension_types = h_entries(env.c_class_entries)
- if h_types or h_vars or h_funcs or h_extension_types:
+ if (h_types or h_vars or h_funcs or h_extension_types):
result.h_file = replace_suffix(result.c_file, ".h")
h_code = Code.CCodeWriter()
Code.GlobalState(h_code)
h_guard = Naming.h_guard_prefix + self.api_name(env)
h_code.put_h_guard(h_guard)
- self.generate_extern_c_macro_definition(h_code)
+ h_code.putln("")
self.generate_type_header_code(h_types, h_code)
h_code.putln("")
api_guard = Naming.api_guard_prefix + self.api_name(env)
h_code.putln("#ifndef %s" % api_guard)
- if h_vars:
- h_code.putln("")
- for entry in h_vars:
- self.generate_public_declaration(entry, h_code, i_code)
- if h_funcs:
- h_code.putln("")
- for entry in h_funcs:
- self.generate_public_declaration(entry, h_code, i_code)
+ h_code.putln("")
+ self.generate_extern_c_macro_definition(h_code)
if h_extension_types:
h_code.putln("")
for entry in h_extension_types:
self.generate_cclass_header_code(entry.type, h_code)
if i_code:
self.generate_cclass_include_code(entry.type, i_code)
+ if h_funcs:
+ h_code.putln("")
+ for entry in h_funcs:
+ self.generate_public_declaration(entry, h_code, i_code)
+ if h_vars:
+ h_code.putln("")
+ for entry in h_vars:
+ self.generate_public_declaration(entry, h_code, i_code)
h_code.putln("")
- h_code.putln("#endif")
+ h_code.putln("#endif /* !%s */" % api_guard)
h_code.putln("")
+ h_code.putln("#if PY_MAJOR_VERSION < 3")
h_code.putln("PyMODINIT_FUNC init%s(void);" % env.module_name)
- h_code.putln("")
+ h_code.putln("#else")
+ h_code.putln("PyMODINIT_FUNC PyInit_%s(void);" % env.module_name)
h_code.putln("#endif")
+ h_code.putln("")
+ h_code.putln("#endif /* !%s */" % h_guard)
f = open_new_file(result.h_file)
try:
def api_name(self, env):
return env.qualified_name.replace(".", "__")
-
+
def generate_api_code(self, env, result):
- api_funcs = []
- public_extension_types = []
- has_api_extension_types = 0
- for entry in env.cfunc_entries:
- if entry.api:
- api_funcs.append(entry)
- for entry in env.c_class_entries:
- if entry.visibility == 'public':
- public_extension_types.append(entry)
- if entry.api:
- has_api_extension_types = 1
- if api_funcs or has_api_extension_types:
+ def api_entries(entries, pxd=1):
+ return [entry for entry in entries
+ if entry.api or (pxd and entry.defined_in_pxd)]
+ api_vars = api_entries(env.var_entries)
+ api_funcs = api_entries(env.cfunc_entries)
+ api_extension_types = api_entries(env.c_class_entries)
+ if api_vars or api_funcs or api_extension_types:
result.api_file = replace_suffix(result.c_file, "_api.h")
h_code = Code.CCodeWriter()
Code.GlobalState(h_code)
- name = self.api_name(env)
- guard = Naming.api_guard_prefix + name
- h_code.put_h_guard(guard)
+ api_guard = Naming.api_guard_prefix + self.api_name(env)
+ h_code.put_h_guard(api_guard)
h_code.putln('#include "Python.h"')
if result.h_file:
h_code.putln('#include "%s"' % os.path.basename(result.h_file))
- for entry in public_extension_types:
- type = entry.type
+ if api_extension_types:
h_code.putln("")
- h_code.putln("static PyTypeObject *%s;" % type.typeptr_cname)
- h_code.putln("#define %s (*%s)" % (
- type.typeobj_cname, type.typeptr_cname))
+ for entry in api_extension_types:
+ type = entry.type
+ h_code.putln("static PyTypeObject *%s = 0;" % type.typeptr_cname)
+ h_code.putln("#define %s (*%s)" % (
+ type.typeobj_cname, type.typeptr_cname))
if api_funcs:
h_code.putln("")
for entry in api_funcs:
type = CPtrType(entry.type)
- h_code.putln("static %s;" % type.declaration_code(entry.cname))
- h_code.putln("")
- h_code.put_h_guard(Naming.api_func_guard + "import_module")
+ cname = env.mangle(Naming.func_prefix, entry.name)
+ h_code.putln("static %s = 0;" % type.declaration_code(cname))
+ h_code.putln("#define %s %s" % (entry.name, cname))
+ if api_vars:
+ h_code.putln("")
+ for entry in api_vars:
+ type = CPtrType(entry.type)
+ cname = env.mangle(Naming.var_prefix, entry.name)
+ h_code.putln("static %s = 0;" % type.declaration_code(cname))
+ h_code.putln("#define %s (*%s)" % (entry.name, cname))
h_code.put(import_module_utility_code.impl)
- h_code.putln("")
- h_code.putln("#endif")
+ if api_vars:
+ h_code.put(voidptr_import_utility_code.impl)
if api_funcs:
- h_code.putln("")
h_code.put(function_import_utility_code.impl)
- if public_extension_types:
- h_code.putln("")
+ if api_extension_types:
h_code.put(type_import_utility_code.impl)
h_code.putln("")
- h_code.putln("static int import_%s(void) {" % name)
+ h_code.putln("static int import_%s(void) {" % self.api_name(env))
h_code.putln("PyObject *module = 0;")
h_code.putln('module = __Pyx_ImportModule("%s");' % env.qualified_name)
h_code.putln("if (!module) goto bad;")
for entry in api_funcs:
+ cname = env.mangle(Naming.func_prefix, entry.name)
sig = entry.type.signature_string()
h_code.putln(
- 'if (__Pyx_ImportFunction(module, "%s", (void (**)(void))&%s, "%s") < 0) goto bad;' % (
- entry.name,
- entry.cname,
- sig))
+ 'if (__Pyx_ImportFunction(module, "%s", (void (**)(void))&%s, "%s") < 0) goto bad;'
+ % (entry.name, cname, sig))
+ for entry in api_vars:
+ cname = env.mangle(Naming.var_prefix, entry.name)
+ sig = entry.type.declaration_code("")
+ h_code.putln(
+ 'if (__Pyx_ImportVoidPtr(module, "%s", (void **)&%s, "%s") < 0) goto bad;'
+ % (entry.name, cname, sig))
h_code.putln("Py_DECREF(module); module = 0;")
- for entry in public_extension_types:
+ for entry in api_extension_types:
self.generate_type_import_call(
entry.type, h_code,
"if (!%s) goto bad;" % entry.type.typeptr_cname)
h_code.putln("return -1;")
h_code.putln("}")
h_code.putln("")
- h_code.putln("#endif")
+ h_code.putln("#endif /* !%s */" % api_guard)
f = open_new_file(result.api_file)
try:
f.close()
def generate_cclass_header_code(self, type, h_code):
- h_code.putln("%s DL_IMPORT(PyTypeObject) %s;" % (
- Naming.extern_c_macro,
+ h_code.putln("%s %s %s;" % (
+ Naming.extern_c_macro,
+ PyrexTypes.public_decl("PyTypeObject", "DL_IMPORT"),
type.typeobj_cname))
def generate_cclass_include_code(self, type, i_code):
self.generate_objstruct_definition(type, code)
for entry in vtabslot_list:
self.generate_objstruct_definition(entry.type, code)
+ self.generate_typeobj_predeclaration(entry, code)
for entry in vtab_list:
- self.generate_typeobject_predeclaration(entry, code)
+ self.generate_typeobj_predeclaration(entry, code)
self.generate_exttype_vtable_struct(entry, code)
self.generate_exttype_vtabptr_declaration(entry, code)
def generate_extern_c_macro_definition(self, code):
name = Naming.extern_c_macro
- code.putln("#ifdef __cplusplus")
- code.putln('#define %s extern "C"' % name)
- code.putln("#else")
- code.putln("#define %s extern" % name)
+ code.putln("#ifndef %s" % name)
+ code.putln(" #ifdef __cplusplus")
+ code.putln(' #define %s extern "C"' % name)
+ code.putln(" #else")
+ code.putln(" #define %s extern" % name)
+ code.putln(" #endif")
code.putln("#endif")
def generate_includes(self, env, cimported_modules, code):
def generate_typedef(self, entry, code):
base_type = entry.type.typedef_base_type
if base_type.is_numeric:
- writer = code.globalstate['numeric_typedefs']
+ try:
+ writer = code.globalstate['numeric_typedefs']
+ except KeyError:
+ writer = code
else:
writer = code
- writer.putln("")
+ writer.mark_pos(entry.pos)
writer.putln("typedef %s;" % base_type.declaration_code(entry.cname))
def sue_header_footer(self, type, kind, name):
code.globalstate.use_utility_code(packed_struct_utility_code)
header, footer = \
self.sue_header_footer(type, kind, type.cname)
- code.putln("")
if packed:
code.putln("#if defined(__SUNPRO_C)")
code.putln(" #pragma pack(1)")
name = entry.cname or entry.name or ""
header, footer = \
self.sue_header_footer(type, "enum", name)
- code.putln("")
code.putln(header)
enum_values = entry.enum_values
if not enum_values:
code.putln(value_code)
code.putln(footer)
- def generate_typeobject_predeclaration(self, entry, code):
+ def generate_typeobj_predeclaration(self, entry, code):
code.putln("")
name = entry.type.typeobj_cname
if name:
if entry.visibility == 'extern' and not entry.in_cinclude:
- code.putln("%s DL_IMPORT(PyTypeObject) %s;" % (
+ code.putln("%s %s %s;" % (
Naming.extern_c_macro,
+ PyrexTypes.public_decl("PyTypeObject", "DL_IMPORT"),
name))
elif entry.visibility == 'public':
- code.putln("%s DL_EXPORT(PyTypeObject) %s;" % (
+ code.putln("%s %s %s;" % (
Naming.extern_c_macro,
+ PyrexTypes.public_decl("PyTypeObject", "DL_EXPORT"),
name))
# ??? Do we really need the rest of this? ???
#else:
- # code.putln("staticforward PyTypeObject %s;" % name)
+ # code.putln("static PyTypeObject %s;" % name)
def generate_exttype_vtable_struct(self, entry, code):
code.mark_pos(entry.pos)
return # Forward declared but never defined
header, footer = \
self.sue_header_footer(type, "struct", type.objstruct_cname)
- code.putln("")
code.putln(header)
base_type = type.base_type
if base_type:
for entry in env.cfunc_entries:
if entry.inline_func_in_pxd or (not entry.in_cinclude and (definition
or entry.defined_in_pxd or entry.visibility == 'extern')):
- if entry.visibility in ('public', 'extern'):
+ if entry.visibility == 'public':
+ storage_class = "%s " % Naming.extern_c_macro
dll_linkage = "DL_EXPORT"
+ elif entry.visibility == 'extern':
+ storage_class = "%s " % Naming.extern_c_macro
+ dll_linkage = "DL_IMPORT"
+ elif entry.visibility == 'private':
+ storage_class = "static "
+ dll_linkage = None
else:
+ storage_class = "static "
dll_linkage = None
type = entry.type
+
if not definition and entry.defined_in_pxd:
type = CPtrType(type)
header = type.declaration_code(entry.cname,
- dll_linkage = dll_linkage)
- if entry.visibility == 'private':
- storage_class = "static "
- elif entry.visibility == 'public':
- storage_class = ""
- else:
- storage_class = "%s " % Naming.extern_c_macro
+ dll_linkage = dll_linkage)
if entry.func_modifiers:
- modifiers = '%s ' % ' '.join([
- modifier.upper() for modifier in entry.func_modifiers])
+ modifiers = "%s " % ' '.join(entry.func_modifiers).upper()
else:
modifiers = ''
code.putln("%s%s%s; /*proto*/" % (
code.putln("/*--- Global init code ---*/")
self.generate_global_init_code(env, code)
+ code.putln("/*--- Variable export code ---*/")
+ self.generate_c_variable_export_code(env, code)
+
code.putln("/*--- Function export code ---*/")
self.generate_c_function_export_code(env, code)
if entry.type.is_pyobject and entry.used:
code.put_init_var_to_py_none(entry, nanny=False)
+ def generate_c_variable_export_code(self, env, code):
+ # Generate code to create PyCFunction wrappers for exported C functions.
+ for entry in env.var_entries:
+ if entry.api or entry.defined_in_pxd:
+ env.use_utility_code(voidptr_export_utility_code)
+ signature = entry.type.declaration_code("")
+ code.putln('if (__Pyx_ExportVoidPtr("%s", (void *)&%s, "%s") < 0) %s' % (
+ entry.name,
+ entry.cname,
+ signature,
+ code.error_goto(self.pos)))
+
def generate_c_function_export_code(self, env, code):
# Generate code to create PyCFunction wrappers for exported C functions.
for entry in env.cfunc_entries:
#------------------------------------------------------------------------------------
+voidptr_export_utility_code = UtilityCode(
+proto = """
+static int __Pyx_ExportVoidPtr(const char *name, void *p, const char *sig); /*proto*/
+""",
+impl = r"""
+static int __Pyx_ExportVoidPtr(const char *name, void *p, const char *sig) {
+ PyObject *d = 0;
+ PyObject *cobj = 0;
+
+ d = PyObject_GetAttrString(%(MODULE)s, (char *)"%(API)s");
+ if (!d) {
+ PyErr_Clear();
+ d = PyDict_New();
+ if (!d)
+ goto bad;
+ Py_INCREF(d);
+ if (PyModule_AddObject(%(MODULE)s, (char *)"%(API)s", d) < 0)
+ goto bad;
+ }
+#if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
+ cobj = PyCapsule_New(p, sig, 0);
+#else
+ cobj = PyCObject_FromVoidPtrAndDesc(p, (void *)sig, 0);
+#endif
+ if (!cobj)
+ goto bad;
+ if (PyDict_SetItemString(d, name, cobj) < 0)
+ goto bad;
+ Py_DECREF(cobj);
+ Py_DECREF(d);
+ return 0;
+bad:
+ Py_XDECREF(cobj);
+ Py_XDECREF(d);
+ return -1;
+}
+""" % {'MODULE': Naming.module_cname, 'API': Naming.api_name}
+)
+
function_export_utility_code = UtilityCode(
proto = """
static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig); /*proto*/
""" % {'MODULE': Naming.module_cname, 'API': Naming.api_name}
)
+voidptr_import_utility_code = UtilityCode(
+proto = """
+static int __Pyx_ImportVoidPtr(PyObject *module, const char *name, void **p, const char *sig); /*proto*/
+""",
+impl = """
+#ifndef __PYX_HAVE_RT_ImportVoidPtr
+#define __PYX_HAVE_RT_ImportVoidPtr
+static int __Pyx_ImportVoidPtr(PyObject *module, const char *name, void **p, const char *sig) {
+ PyObject *d = 0;
+ PyObject *cobj = 0;
+
+ d = PyObject_GetAttrString(module, (char *)"%(API)s");
+ if (!d)
+ goto bad;
+ cobj = PyDict_GetItemString(d, name);
+ if (!cobj) {
+ PyErr_Format(PyExc_ImportError,
+ "%%s does not export expected C variable %%s",
+ PyModule_GetName(module), name);
+ goto bad;
+ }
+#if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
+ if (!PyCapsule_IsValid(cobj, sig)) {
+ PyErr_Format(PyExc_TypeError,
+ "C variable %%s.%%s has wrong signature (expected %%s, got %%s)",
+ PyModule_GetName(module), name, sig, PyCapsule_GetName(cobj));
+ goto bad;
+ }
+ *p = PyCapsule_GetPointer(cobj, sig);
+#else
+ {const char *desc, *s1, *s2;
+ desc = (const char *)PyCObject_GetDesc(cobj);
+ if (!desc)
+ goto bad;
+ s1 = desc; s2 = sig;
+ while (*s1 != '\\0' && *s1 == *s2) { s1++; s2++; }
+ if (*s1 != *s2) {
+ PyErr_Format(PyExc_TypeError,
+ "C variable %%s.%%s has wrong signature (expected %%s, got %%s)",
+ PyModule_GetName(module), name, sig, desc);
+ goto bad;
+ }
+ *p = PyCObject_AsVoidPtr(cobj);}
+#endif
+ if (!(*p))
+ goto bad;
+ Py_DECREF(d);
+ return 0;
+bad:
+ Py_XDECREF(d);
+ return -1;
+}
+#endif
+""" % dict(API = Naming.api_name)
+)
+
function_import_utility_code = UtilityCode(
proto = """
static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**f)(void), const char *sig); /*proto*/
error(self.pos,
"Only 'extern' C variable declaration allowed in .pxd file")
entry = dest_scope.declare_var(name, type, declarator.pos,
- cname = cname, visibility = visibility, is_cdef = 1)
+ cname=cname, visibility=visibility, api=self.api, is_cdef=1)
entry.needs_property = need_property
# kind "struct" or "union"
# typedef_flag boolean
# visibility "public" or "private"
+ # api boolean
# in_pxd boolean
# attributes [CVarDefNode] or None
# entry Entry
scope = StructOrUnionScope(self.name)
self.entry = env.declare_struct_or_union(
self.name, self.kind, scope, self.typedef_flag, self.pos,
- self.cname, visibility = self.visibility, packed = self.packed)
+ self.cname, visibility = self.visibility, api = self.api,
+ packed = self.packed)
if self.attributes is not None:
if self.in_pxd and not env.in_cinclude:
self.entry.defined_in_pxd = 1
# items [CEnumDefItemNode]
# typedef_flag boolean
# visibility "public" or "private"
+ # api boolean
# in_pxd boolean
# entry Entry
-
+
child_attrs = ["items"]
def analyse_declarations(self, env):
self.entry = env.declare_enum(self.name, self.pos,
cname = self.cname, typedef_flag = self.typedef_flag,
- visibility = self.visibility)
+ visibility = self.visibility, api = self.api)
if self.items is not None:
if self.in_pxd and not env.in_cinclude:
self.entry.defined_in_pxd = 1
pass
def generate_execution_code(self, code):
- if self.visibility == 'public':
+ if self.visibility == 'public' or self.api:
temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
for item in self.entry.enum_values:
code.putln("%s = PyInt_FromLong(%s); %s" % (
if not self.value.type.is_int:
self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
self.value.analyse_const_expression(env)
- entry = env.declare_const(self.name, enum_entry.type,
+ entry = env.declare_const(self.name, enum_entry.type,
self.value, self.pos, cname = self.cname,
- visibility = enum_entry.visibility)
+ visibility = enum_entry.visibility, api = enum_entry.api)
enum_entry.enum_values.append(entry)
# base_type CBaseTypeNode
# declarator CDeclaratorNode
# visibility "public" or "private"
+ # api boolean
# in_pxd boolean
child_attrs = ["base_type", "declarator"]
name = name_declarator.name
cname = name_declarator.cname
entry = env.declare_typedef(name, type, self.pos,
- cname = cname, visibility = self.visibility)
+ cname = cname, visibility = self.visibility, api = self.api)
if self.in_pxd and not env.in_cinclude:
entry.defined_in_pxd = 1
-
+
def analyse_expressions(self, env):
pass
def generate_execution_code(self, code):
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:
if cname is None:
cname = self.entry.func_cname
entity = type.function_header_code(cname, ', '.join(arg_decls))
- if visibility == 'public':
- dll_linkage = "DL_EXPORT"
+ if self.entry.visibility == 'private':
+ storage_class = "static "
else:
- dll_linkage = None
- header = self.return_type.declaration_code(entity,
- dll_linkage = dll_linkage)
- if visibility == 'extern':
- storage_class = "%s " % Naming.extern_c_macro
- elif visibility == 'public':
storage_class = ""
- else:
- storage_class = "static "
+ dll_linkage = None
+ modifiers = ""
if 'inline' in self.modifiers:
self.modifiers[self.modifiers.index('inline')] = 'cython_inline'
- code.putln("%s%s %s {" % (
- storage_class,
- ' '.join(self.modifiers).upper(), # macro forms
- header))
+ if self.modifiers:
+ modifiers = "%s " % ' '.join(self.modifiers).upper()
+
+ header = self.return_type.declaration_code(entity, dll_linkage=dll_linkage)
+ #print (storage_class, modifiers, header)
+ code.putln("%s%s%s {" % (storage_class, modifiers, header))
def generate_argument_declarations(self, env, code):
for arg in self.args:
return Nodes.CEnumDefNode(
pos, name = name, cname = cname, items = items,
typedef_flag = ctx.typedef_flag, visibility = ctx.visibility,
- in_pxd = ctx.level == 'module_pxd')
+ api = ctx.api, in_pxd = ctx.level == 'module_pxd')
def p_c_enum_line(s, ctx, items):
if s.sy != 'pass':
s.expect_dedent()
else:
s.expect_newline("Syntax error in struct or union definition")
- return Nodes.CStructOrUnionDefNode(pos,
+ return Nodes.CStructOrUnionDefNode(pos,
name = name, cname = cname, kind = kind, attributes = attributes,
typedef_flag = ctx.typedef_flag, visibility = ctx.visibility,
- in_pxd = ctx.level == 'module_pxd', packed = packed)
+ api = ctx.api, in_pxd = ctx.level == 'module_pxd', packed = packed)
def p_visibility(s, prev_visibility):
pos = s.position()
s.expect_newline("Syntax error in ctypedef statement")
return Nodes.CTypeDefNode(
pos, base_type = base_type,
- declarator = declarator, visibility = visibility,
+ declarator = declarator,
+ visibility = visibility, api = api,
in_pxd = ctx.level == 'module_pxd')
def p_decorators(s):
base_class_module = ".".join(base_class_path[:-1])
base_class_name = base_class_path[-1]
if s.sy == '[':
- if ctx.visibility not in ('public', 'extern'):
- error(s.position(), "Name options only allowed for 'public' or 'extern' C class")
+ if ctx.visibility not in ('public', 'extern') and not ctx.api:
+ error(s.position(), "Name options only allowed for 'public', 'api', or 'extern' C class")
objstruct_name, typeobj_name = p_c_class_options(s)
if s.sy == ':':
if ctx.level == 'module_pxd':
error(pos, "Type object name specification required for 'public' C class")
elif ctx.visibility == 'private':
if ctx.api:
- error(pos, "Only 'public' C class can be declared 'api'")
+ if not objstruct_name:
+ error(pos, "Object struct name specification required for 'api' C class")
+ if not typeobj_name:
+ error(pos, "Type object name specification required for 'api' C class")
else:
error(pos, "Invalid class visibility '%s'" % ctx.visibility)
return Nodes.CClassDefNode(pos,
visibility="extern")
scope.parent_type = self
scope.directives = {}
- scope.declare_var("real", self.real_type, None, "real", is_cdef=True)
- scope.declare_var("imag", self.real_type, None, "imag", is_cdef=True)
+ scope.declare_var("real", self.real_type, None, cname="real", is_cdef=True)
+ scope.declare_var("imag", self.real_type, None, cname="imag", is_cdef=True)
entry = scope.declare_cfunction(
"conjugate",
CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
def qualify_name(self, name):
return EncodedString("%s.%s" % (self.qualified_name, name))
- def declare_const(self, name, type, value, pos, cname = None, visibility = 'private'):
+ def declare_const(self, name, type, value, pos, cname = None, visibility = 'private', api = 0):
# Add an entry for a named constant.
if not cname:
- if self.in_cinclude or visibility == 'public':
+ if self.in_cinclude or (visibility == 'public' or api):
cname = name
else:
cname = self.mangle(Naming.enum_prefix, name)
return entry
def declare_type(self, name, type, pos,
- cname = None, visibility = 'private', defining = 1, shadow = 0):
+ cname = None, visibility = 'private', api = 0, defining = 1, shadow = 0):
# Add an entry for a type definition.
if not cname:
cname = name
entry = self.declare(name, cname, type, pos, visibility, shadow)
entry.is_type = 1
+ entry.api = api
if defining:
self.type_entries.append(entry)
# here we would set as_variable to an object representing this type
return entry
def declare_typedef(self, name, base_type, pos, cname = None,
- visibility = 'private'):
+ visibility = 'private', api = 0):
if not cname:
- if self.in_cinclude or visibility == 'public':
+ if self.in_cinclude or (visibility == 'public' or api):
cname = name
else:
cname = self.mangle(Naming.type_prefix, name)
except ValueError, e:
error(pos, e.args[0])
type = PyrexTypes.error_type
- entry = self.declare_type(name, type, pos, cname, visibility)
+ entry = self.declare_type(name, type, pos, cname,
+ visibility = visibility, api = api)
type.qualified_name = entry.qualified_name
return entry
-
- def declare_struct_or_union(self, name, kind, scope,
- typedef_flag, pos, cname = None, visibility = 'private',
- packed = False):
+
+ def declare_struct_or_union(self, name, kind, scope,
+ typedef_flag, pos, cname = None,
+ visibility = 'private', api = 0,
+ packed = False):
# Add an entry for a struct or union definition.
if not cname:
- if self.in_cinclude or visibility == 'public':
+ if self.in_cinclude or (visibility == 'public' or api):
cname = name
else:
cname = self.mangle(Naming.type_prefix, name)
type = PyrexTypes.CStructOrUnionType(
name, kind, scope, typedef_flag, cname, packed)
entry = self.declare_type(name, type, pos, cname,
- visibility = visibility, defining = scope is not None)
+ visibility = visibility, api = api,
+ defining = scope is not None)
self.sue_entries.append(entry)
type.entry = entry
else:
if entry.visibility != visibility:
error(pos, "'%s' previously declared as '%s'" % (
entry.name, entry.visibility))
-
+
def declare_enum(self, name, pos, cname, typedef_flag,
- visibility = 'private'):
+ visibility = 'private', api = 0):
if name:
if not cname:
- if self.in_cinclude or visibility == 'public':
+ if self.in_cinclude or (visibility == 'public' or api):
cname = name
else:
cname = self.mangle(Naming.type_prefix, name)
else:
type = PyrexTypes.c_anon_enum_type
entry = self.declare_type(name, type, pos, cname = cname,
- visibility = visibility)
+ visibility = visibility, api = api)
entry.enum_values = []
self.sue_entries.append(entry)
- return entry
+ return entry
def declare_var(self, name, type, pos,
- cname = None, visibility = 'private', is_cdef = 0):
+ cname = None, visibility = 'private', api = 0, is_cdef = 0):
# Add an entry for a variable.
if not cname:
if visibility != 'private':
error(pos, "C++ class must have a default constructor to be stack allocated")
entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1
+ entry.api = api
self.control_flow.set_state((), (name, 'initialized'), False)
return entry
return entry
def declare_var(self, name, type, pos,
- cname = None, visibility = 'private', is_cdef = 0):
+ cname = None, visibility = 'private', api = 0, is_cdef = 0):
# Add an entry for a global variable. If it is a Python
# object type, and not declared with cdef, it will live
# in the module dictionary, otherwise it will be a C
# global variable.
entry = Scope.declare_var(self, name, type, pos,
- cname, visibility, is_cdef)
+ cname=cname, visibility=visibility, api=api, is_cdef=is_cdef)
if not visibility in ('private', 'public', 'extern'):
error(pos, "Module-level variable cannot be declared %s" % visibility)
if not is_cdef:
buffer_defaults = None, shadow = 0):
# If this is a non-extern typedef class, expose the typedef, but use
# the non-typedef struct internally to avoid needing forward
- # declarations for anonymous structs.
+ # declarations for anonymous structs.
if typedef_flag and visibility != 'extern':
- if visibility != 'public':
- warning(pos, "ctypedef only valid for public and extern classes", 2)
+ if not (visibility == 'public' or api):
+ warning(pos, "ctypedef only valid for 'extern' , 'public', and 'api'", 2)
objtypedef_cname = objstruct_cname
typedef_flag = 0
else:
return entry
def declare_var(self, name, type, pos,
- cname = None, visibility = 'private', is_cdef = 0):
+ cname = None, visibility = 'private', api = 0, is_cdef = 0):
# Add an entry for a local variable.
if visibility in ('public', 'readonly'):
error(pos, "Local variable cannot be declared %s" % visibility)
entry = Scope.declare_var(self, name, type, pos,
- cname, visibility, is_cdef)
+ cname=cname, visibility=visibility, api=api, is_cdef=is_cdef)
if type.is_pyobject and not Options.init_local_none:
entry.init = "0"
entry.init_to_none = (type.is_pyobject or type.is_unspecified) and Options.init_local_none
return '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(prefix, name))
def declare_var(self, name, type, pos,
- cname = None, visibility = 'private', is_cdef = True):
+ cname = None, visibility = 'private', api = 0, is_cdef = True):
if type is unspecified_type:
# if the outer scope defines a type for this variable, inherit it
outer_entry = self.outer_scope.lookup(name)
Scope.__init__(self, name, None, None)
def declare_var(self, name, type, pos,
- cname = None, visibility = 'private', is_cdef = 0, allow_pyobject = 0):
+ cname = None, visibility = 'private', api = 0, is_cdef = 0, allow_pyobject = 0):
# Add an entry for an attribute.
if not cname:
cname = name
def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'private', defining = 0,
api = 0, in_pxd = 0, modifiers = ()): # currently no utility code ...
- return self.declare_var(name, type, pos, cname, visibility)
+ return self.declare_var(name, type, pos,
+ cname=cname, visibility=visibility)
class ClassScope(Scope):
# Abstract base class for namespace of
is_py_class_scope = 1
def declare_var(self, name, type, pos,
- cname = None, visibility = 'private', is_cdef = 0):
+ cname = None, visibility = 'private', api = 0, is_cdef = 0):
if type is unspecified_type:
type = py_object_type
# Add an entry for a class attribute.
entry = Scope.declare_var(self, name, type, pos,
- cname, visibility, is_cdef)
+ cname=cname, visibility=visibility, api=api, is_cdef=is_cdef)
entry.is_pyglobal = 1
entry.is_pyclass_attr = 1
return entry
self.parent_type.base_type.scope.needs_gc())
def declare_var(self, name, type, pos,
- cname = None, visibility = 'private', is_cdef = 0):
+ cname = None, visibility = 'private', api = 0, is_cdef = 0):
if is_cdef:
# Add an entry for an attribute.
if self.defined:
type = py_object_type
# Add an entry for a class attribute.
entry = Scope.declare_var(self, name, type, pos,
- cname, visibility, is_cdef)
+ cname=cname, visibility=visibility, api=api, is_cdef=is_cdef)
entry.is_member = 1
entry.is_pyglobal = 1 # xxx: is_pyglobal changes behaviour in so many places that
# I keep it in for now. is_member should be enough
if name == "__new__":
error(pos, "__new__ method of extension type will change semantics "
"in a future version of Pyrex and Cython. Use __cinit__ instead.")
- entry = self.declare_var(name, py_object_type, pos, visibility='extern')
+ entry = self.declare_var(name, py_object_type, pos,
+ visibility='extern')
special_sig = get_special_method_signature(name)
if special_sig:
# Special methods get put in the method table with a particular
self.inherited_var_entries = []
def declare_var(self, name, type, pos,
- cname = None, visibility = 'extern', is_cdef = 0, allow_pyobject = 0):
+ cname = None, visibility = 'extern', api = 0,
+ is_cdef = 0, allow_pyobject = 0):
# Add an entry for an attribute.
if not cname:
cname = name
error(pos, "no matching function for call to %s::%s()" %
(self.default_constructor, self.default_constructor))
- def declare_cfunction(self, name, type, pos,
- cname = None, visibility = 'extern', defining = 0,
- api = 0, in_pxd = 0, modifiers = (), utility_code = None):
+ def declare_cfunction(self, name, type, pos, cname = None,
+ visibility = 'extern', api = 0, defining = 0,
+ in_pxd = 0, modifiers = (), utility_code = None):
if name == self.name.split('::')[-1] and cname is None:
self.check_base_default_constructor(pos)
name = '<init>'
type.return_type = self.lookup(self.name).type
prev_entry = self.lookup_here(name)
- entry = self.declare_var(name, type, pos, cname, visibility)
+ entry = self.declare_var(name, type, pos,
+ cname=cname, visibility=visibility)
if prev_entry:
entry.overloaded_alternatives = prev_entry.all_alternatives()
entry.utility_code = utility_code
self.inherited_var_entries.append(entry)
for base_entry in base_scope.cfunc_entries:
entry = self.declare_cfunction(base_entry.name, base_entry.type,
- base_entry.pos, base_entry.cname,
- base_entry.visibility, base_entry.func_modifiers,
+ base_entry.pos, base_entry.cname,
+ base_entry.visibility, 0,
+ modifiers = base_entry.func_modifiers,
utility_code = base_entry.utility_code)
entry.is_inherited = 1
cdef public Zax *blarg
+cdef public C c_pub = C()
+cdef api C c_api = C()
+
+cdef public dict o_pub = C()
+cdef api list o_api = C()
+
cdef api float f(Foo *x):
pass
--- /dev/null
+# --
+
+ctypedef int Int0
+ctypedef api int Int1
+
+ctypedef enum EnumA0: EA0
+ctypedef api enum EnumA1: EA1
+
+cdef enum EnumB0: EB0=0
+cdef api enum EnumB1: EB1=1
+
+cdef Int0 i0 = 0
+cdef EnumA0 ea0 = EA0
+cdef EnumB0 eb0 = EB0
+
+cdef api Int1 i1 = 0
+cdef api EnumA1 ea1 = EA1
+cdef api EnumB1 eb1 = EB1
+
+# --
+
+ctypedef struct StructA0:
+ int SA0
+ctypedef api struct StructA1:
+ int SA1
+
+cdef struct StructB0:
+ int SB0
+cdef api struct StructB1:
+ int SB1
+
+cdef StructA0 sa0 = {'SA0':0}
+cdef StructB0 sb0 = {'SB0':2}
+
+cdef api StructA1 sa1 = {'SA1':1}
+cdef api StructB1 sb1 = {'SB1':3}
+
+# --
+
+ctypedef class Foo0: pass
+ctypedef api class Foo1 [type PyFoo1_Type, object PyFoo1_Object]: pass
+
+cdef class Bar0: pass
+cdef api class Bar1 [type PyBar1_Type, object PyBar1_Object]: pass
+
+cdef Foo0 f0 = None
+cdef Bar0 b0 = None
+
+cdef api Foo1 f1 = None
+cdef api Bar1 b1 = None
+
+# --
+
+cdef void bar0(): pass
+cdef api void bar1(): pass
+
+cdef void* spam0(object o) except NULL: return NULL
+cdef api void* spam1(object o) except NULL: return NULL
+
+bar0()
+bar1()
+spam0(None)
+spam1(None)
+
+# --
--- /dev/null
+# --
+
+ctypedef int Int0
+ctypedef public int Int1
+ctypedef api int Int2
+ctypedef public api int Int3
+
+ctypedef enum EnumA0: EA0
+ctypedef public enum EnumA1: EA1
+ctypedef api enum EnumA2: EA2
+ctypedef public api enum EnumA3: EA3
+
+cdef enum EnumB0: EB0=0
+cdef public enum EnumB1: EB1=1
+cdef api enum EnumB2: EB2=2
+cdef public api enum EnumB3: EB3=3
+
+# --
+
+ctypedef struct StructA0:
+ int SA0
+ctypedef public struct StructA1:
+ int SA1
+ctypedef api struct StructA2:
+ int SA2
+ctypedef public api struct StructA3:
+ int SA3
+
+cdef struct StructB0:
+ int SB0
+cdef public struct StructB1:
+ int SB1
+cdef api struct StructB2:
+ int SB2
+cdef public api struct StructB3:
+ int SB3
+
+# --
+
+ctypedef class Foo0: pass
+ctypedef public class Foo1 [type PyFoo1_Type, object PyFoo1_Object]: pass
+ctypedef api class Foo2 [type PyFoo2_Type, object PyFoo2_Object]: pass
+ctypedef public api class Foo3 [type PyFoo3_Type, object PyFoo3_Object]: pass
+
+cdef class Bar0: pass
+cdef public class Bar1 [type PyBar1_Type, object PyBar1_Object]: pass
+cdef api class Bar2 [type PyBar2_Type, object PyBar2_Object]: pass
+cdef public api class Bar3 [type PyBar3_Type, object PyBar3_Object]: pass
+
+# --
+
+cdef void bar0(): pass
+cdef public void bar1(): pass
+cdef api void bar2(): pass
+cdef public api void bar3(): pass
+
+cdef void* spam0(object o) except NULL: return NULL
+cdef public void* spam1(object o) except NULL: return NULL
+cdef api void* spam2(object o) except NULL: return NULL
+cdef public api void* spam3(object o) except NULL: return NULL
+
+bar0()
+spam0(None)
+
+# --
+
+cdef double d0 = 0
+cdef public double d1 = 1
+cdef api double d2 = 2
+cdef public api double d3 = 3
+
+cdef object o0 = None
+cdef public object o1 = None
+cdef api object o2 = None
+cdef public api object o3 = None
+
+# --
--- /dev/null
+# --
+
+ctypedef int Int0
+ctypedef public int Int1
+
+ctypedef enum EnumA0: EA0
+ctypedef public enum EnumA1: EA1
+
+cdef enum EnumB0: EB0=0
+cdef public enum EnumB1: EB1=1
+
+cdef Int0 i0 = 0
+cdef EnumA0 ea0 = EA0
+cdef EnumB0 eb0 = EB0
+
+cdef public Int1 i1 = 0
+cdef public EnumA1 ea1 = EA1
+cdef public EnumB1 eb1 = EB1
+
+# --
+
+ctypedef struct StructA0:
+ int SA0
+ctypedef public struct StructA1:
+ int SA1
+
+cdef struct StructB0:
+ int SB0
+cdef public struct StructB1:
+ int SB1
+
+cdef StructA0 sa0 = {'SA0':0}
+cdef StructB0 sb0 = {'SB0':2}
+
+cdef public StructA1 sa1 = {'SA1':1}
+cdef public StructB1 sb1 = {'SB1':3}
+
+# --
+
+ctypedef class Foo0: pass
+ctypedef public class Foo1 [type PyFoo1_Type, object PyFoo1_Object]: pass
+
+cdef class Bar0: pass
+cdef public class Bar1 [type PyBar1_Type, object PyBar1_Object]: pass
+
+cdef Foo0 f0 = None
+cdef Bar0 b0 = None
+
+cdef public Foo1 f1 = None
+cdef public Bar1 b1 = None
+
+# --
+
+cdef void bar0(): pass
+cdef public void bar1(): pass
+
+cdef void* spam0(object o) except NULL: return NULL
+cdef public void* spam1(object o) except NULL: return NULL
+
+bar0()
+bar1()
+spam0(None)
+spam1(None)
+
+# --
--- /dev/null
+# --
+
+ctypedef int Int0
+ctypedef public int Int1
+ctypedef api int Int2
+ctypedef public api int Int3
+
+ctypedef enum EnumA0: EA0
+ctypedef public enum EnumA1: EA1
+ctypedef api enum EnumA2: EA2
+ctypedef public api enum EnumA3: EA3
+
+cdef enum EnumB0: EB0=0
+cdef public enum EnumB1: EB1=1
+cdef api enum EnumB2: EB2=2
+cdef public api enum EnumB3: EB3=3
+
+# --
+
+ctypedef struct StructA0:
+ int SA0
+ctypedef public struct StructA1:
+ int SA1
+ctypedef api struct StructA2:
+ int SA2
+ctypedef public api struct StructA3:
+ int SA3
+
+cdef struct StructB0:
+ int SB0
+cdef public struct StructB1:
+ int SB1
+cdef api struct StructB2:
+ int SB2
+cdef public api struct StructB3:
+ int SB3
+
+# --
+
+ctypedef class Foo0: pass
+ctypedef public class Foo1 [type PyFoo1_Type, object PyFoo1_Object]: pass
+ctypedef api class Foo2 [type PyFoo2_Type, object PyFoo2_Object]: pass
+ctypedef public api class Foo3 [type PyFoo3_Type, object PyFoo3_Object]: pass
+
+cdef class Bar0: pass
+cdef public class Bar1 [type PyBar1_Type, object PyBar1_Object]: pass
+cdef api class Bar2 [type PyBar2_Type, object PyBar2_Object]: pass
+cdef public api class Bar3 [type PyBar3_Type, object PyBar3_Object]: pass
+
+# --
+
+cdef inline void bar0(): pass
+cdef public void bar1()
+cdef api void bar2()
+cdef public api void bar3()
+
+cdef inline void* spam0(object o) except NULL: return NULL
+cdef public void* spam1(object o) except NULL
+cdef api void* spam2(object o) nogil except NULL
+cdef public api void* spam3(object o) except NULL with gil
+
+# --
+
+#cdef public int i1
+#cdef api int i2
+#cdef public api int i3
+
+# --
--- /dev/null
+cdef class Foo1: pass
+cdef class Foo2: pass
+cdef class Foo3: pass
+
+cdef class Bar1: pass
+cdef class Bar2: pass
+cdef class Bar3: pass
+
+cdef public void bar1(): pass
+cdef api void bar2(): pass
+cdef public api void bar3(): pass
+
+cdef public void* spam1(object o) except NULL: return NULL
+cdef api void* spam2(object o) nogil except NULL: return NULL
+cdef public api void* spam3(object o) except NULL with gil: return NULL
>>> import sys
>>> sys.getrefcount(Foo.__pyx_vtable__)
2
->>> sys.getrefcount(__pyx_capi__['spam'])
+>>> sys.getrefcount(__pyx_capi__['ten'])
2
+>>> sys.getrefcount(__pyx_capi__['pi'])
+2
+>>> sys.getrefcount(__pyx_capi__['obj'])
+2
+>>> sys.getrefcount(__pyx_capi__['dct'])
+2
+>>> sys.getrefcount(__pyx_capi__['one'])
+2
+>>> sys.getrefcount(__pyx_capi__['two'])
+Traceback (most recent call last):
+ ...
+KeyError: 'two'
"""
cdef public api class Foo [type FooType, object FooObject]:
cdef api void spam():
pass
+
+cdef api int ten = 10
+cdef api double pi = 3.14
+cdef api object obj = object()
+cdef api dict dct = {}
+
+cdef public api int one = 1
+cdef public int two = 2
+