Commit 7c6f0728 authored by Lisandro Dalcin's avatar Lisandro Dalcin

Support pxd/public/api import/export for C variables

parent 4b89cc34
......@@ -8,6 +8,7 @@ Cython/Runtime/refnanny.c
BUILD/
build/
!tests/build/
dist/
.gitrev
.coverage
......
......@@ -1166,39 +1166,19 @@ class CCodeWriter(object):
self.funcstate.use_label(lbl)
self.putln("goto %s;" % lbl)
def put_var_declarations(self, entries, static = 0, dll_linkage = None,
definition = True):
for entry in entries:
if not entry.in_cinclude:
self.put_var_declaration(entry, static, dll_linkage, definition)
def put_var_declaration(self, entry, static = 0, dll_linkage = None,
definition = True):
def put_var_declaration(self, entry, storage_class="",
dll_linkage = None, definition = True):
#print "Code.put_var_declaration:", entry.name, "definition =", definition ###
if entry.in_closure:
return
visibility = entry.visibility
if visibility == 'private' and not definition:
#print "...private and not definition, skipping" ###
if entry.visibility == 'private' and not (definition or entry.defined_in_pxd):
#print "...private and not definition, skipping", entry.cname ###
return
if not entry.used and visibility == "private":
#print "not used and private, skipping", entry.cname ###
if entry.visibility == "private" and not entry.used:
#print "...private and not used, skipping", entry.cname ###
return
storage_class = ""
if visibility == 'extern':
storage_class = Naming.extern_c_macro
elif visibility == 'public':
if not definition:
storage_class = Naming.extern_c_macro
elif visibility == 'private':
if static:
storage_class = "static"
if storage_class:
self.put("%s " % storage_class)
if visibility != 'public':
dll_linkage = None
self.put(entry.type.declaration_code(entry.cname,
dll_linkage = dll_linkage))
self.put(entry.type.declaration_code(
entry.cname, dll_linkage = dll_linkage))
if entry.init is not None:
self.put_safe(" = %s" % entry.type.literal_code(entry.init))
self.putln(";")
......
......@@ -201,7 +201,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
h_code.putln("")
for entry in api_vars:
type = CPtrType(entry.type)
cname = env.mangle(Naming.var_prefix, entry.name)
cname = env.mangle(Naming.varptr_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)
......@@ -223,7 +223,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
'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)
cname = env.mangle(Naming.varptr_prefix, entry.name)
sig = entry.type.declaration_code("")
h_code.putln(
'if (__Pyx_ImportVoidPtr(module, "%s", (void **)&%s, "%s") < 0) goto bad;'
......@@ -290,7 +290,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('#define __Pyx_MODULE_NAME "%s"' % self.full_module_name)
code.putln("int %s%s = 0;" % (Naming.module_is_main, self.full_module_name.replace('.', '__')))
code.putln("")
code.putln("/* Implementation of %s */" % env.qualified_name)
code.putln("/* Implementation of '%s' */" % env.qualified_name)
code = globalstate['all_the_rest']
......@@ -449,17 +449,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_declarations_for_modules(self, env, modules, globalstate):
typecode = globalstate['type_declarations']
typecode.putln("")
typecode.putln("/* Type declarations */")
typecode.putln("/*--- Type declarations ---*/")
vtab_list, vtabslot_list = self.sort_type_hierarchy(modules, env)
self.generate_type_definitions(
env, modules, vtab_list, vtabslot_list, typecode)
modulecode = globalstate['module_declarations']
for module in modules:
defined_here = module is env
modulecode.putln("/* Module declarations from %s */" %
module.qualified_name)
self.generate_global_declarations(module, modulecode, defined_here)
self.generate_cfunction_predeclarations(module, modulecode, defined_here)
modulecode.putln("")
modulecode.putln("/* Module declarations from '%s' */" % module.qualified_name)
self.generate_c_class_declarations(module, modulecode, defined_here)
self.generate_cvariable_declarations(module, modulecode, defined_here)
self.generate_cfunction_declarations(module, modulecode, defined_here)
def generate_module_preamble(self, env, cimported_modules, code):
code.putln("/* Generated by Cython %s on %s */" % (
......@@ -978,25 +979,68 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# Only for exposing public typedef name.
code.putln("typedef struct %s %s;" % (type.objstruct_cname, type.objtypedef_cname))
def generate_global_declarations(self, env, code, definition):
code.putln("")
def generate_c_class_declarations(self, env, code, definition):
for entry in env.c_class_entries:
if definition or entry.defined_in_pxd:
code.putln("static PyTypeObject *%s = 0;" %
entry.type.typeptr_cname)
code.put_var_declarations(env.var_entries, static = 1,
dll_linkage = "DL_EXPORT", definition = definition)
def generate_cfunction_predeclarations(self, env, code, definition):
def generate_cvariable_declarations(self, env, code, definition):
for entry in env.var_entries:
if (entry.in_cinclude or entry.in_closure or
(entry.visibility == 'private' and
not (entry.defined_in_pxd or entry.used))):
continue
storage_class = None
dll_linkage = None
cname = None
init = None
if entry.visibility == 'extern':
storage_class = Naming.extern_c_macro
dll_linkage = "DL_IMPORT"
elif entry.visibility == 'public':
if definition:
dll_linkage = "DL_EXPORT"
else:
storage_class = Naming.extern_c_macro
dll_linkage = "DL_IMPORT"
elif entry.visibility == 'private':
storage_class = "static"
if entry.defined_in_pxd and not definition:
type = CPtrType(entry.type)
storage_class = "static"
dll_linkage = None
cname = env.mangle(Naming.varptr_prefix, entry.name)
init = 0
else:
type = entry.type
cname = entry.cname
if entry.init is not None:
init = type.literal_code(entry.init)
if storage_class:
code.put("%s " % storage_class)
code.put(type.declaration_code(
cname, dll_linkage = dll_linkage))
if init is not None:
code.put_safe(" = %s" % init)
code.putln(";")
if entry.cname != cname:
code.putln("#define %s (*%s)" % (entry.cname, cname))
def generate_cfunction_declarations(self, env, code, definition):
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 == 'public':
storage_class = ""
dll_linkage = "DL_EXPORT"
elif entry.visibility == 'extern':
if entry.visibility == 'extern':
storage_class = "%s " % Naming.extern_c_macro
dll_linkage = "DL_IMPORT"
elif entry.visibility == 'public':
storage_class = ""
dll_linkage = "DL_EXPORT"
elif entry.visibility == 'private':
storage_class = "static "
dll_linkage = None
......@@ -1009,6 +1053,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
storage_class = "static "
dll_linkage = None
type = CPtrType(type)
header = type.declaration_code(entry.cname,
dll_linkage = dll_linkage)
if entry.func_modifiers:
......@@ -1851,6 +1896,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
for module in imported_modules:
self.generate_type_import_code_for_module(module, env, code)
code.putln("/*--- Variable import code ---*/")
for module in imported_modules:
self.generate_c_variable_import_code_for_module(module, env, code)
code.putln("/*--- Function import code ---*/")
for module in imported_modules:
self.generate_c_function_import_code_for_module(module, env, code)
......@@ -2030,21 +2079,27 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_c_variable_export_code(self, env, code):
# Generate code to create PyCFunction wrappers for exported C functions.
entries = []
for entry in env.var_entries:
if entry.api or entry.defined_in_pxd:
entries.append(entry)
if entries:
env.use_utility_code(voidptr_export_utility_code)
for entry in entries:
signature = entry.type.declaration_code("")
code.putln('if (__Pyx_ExportVoidPtr("%s", (void *)&%s, "%s") < 0) %s' % (
entry.name,
entry.cname,
signature,
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.
entries = []
for entry in env.cfunc_entries:
if entry.api or entry.defined_in_pxd:
entries.append(entry)
if entries:
env.use_utility_code(function_export_utility_code)
for entry in entries:
signature = entry.type.signature_string()
code.putln('if (__Pyx_ExportFunction("%s", (void (*)(void))%s, "%s") < 0) %s' % (
entry.name,
......@@ -2060,6 +2115,34 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if entry.defined_in_pxd:
self.generate_type_import_code(env, entry.type, entry.pos, code)
def generate_c_variable_import_code_for_module(self, module, env, code):
# Generate import code for all exported C functions in a cimported module.
entries = []
for entry in module.var_entries:
if entry.defined_in_pxd:
entries.append(entry)
if entries:
env.use_utility_code(import_module_utility_code)
env.use_utility_code(voidptr_import_utility_code)
temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
code.putln(
'%s = __Pyx_ImportModule("%s"); if (!%s) %s' % (
temp,
module.qualified_name,
temp,
code.error_goto(self.pos)))
for entry in entries:
if env is module:
cname = entry.cname
else:
cname = module.mangle(Naming.varptr_prefix, entry.name)
signature = entry.type.declaration_code("")
code.putln(
'if (__Pyx_ImportVoidPtr(%s, "%s", (void **)&%s, "%s") < 0) %s' % (
temp, entry.name, cname, signature,
code.error_goto(self.pos)))
code.putln("Py_DECREF(%s); %s = 0;" % (temp, temp))
def generate_c_function_import_code_for_module(self, module, env, code):
# Generate import code for all exported C functions in a cimported module.
entries = []
......
......@@ -36,6 +36,7 @@ prop_set_prefix = pyrex_prefix + "setprop_"
type_prefix = pyrex_prefix + "t_"
typeobj_prefix = pyrex_prefix + "type_"
var_prefix = pyrex_prefix + "v_"
varptr_prefix = pyrex_prefix + "vp_"
wrapperbase_prefix= pyrex_prefix + "wrapperbase_"
bufstruct_prefix = pyrex_prefix + "bstruct_"
bufstride_prefix = pyrex_prefix + "bstride_"
......
......@@ -969,18 +969,16 @@ class CVarDefNode(StatNode):
return
if type.is_cfunction:
entry = dest_scope.declare_cfunction(name, type, declarator.pos,
cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
api = self.api)
cname = cname, visibility = self.visibility,
in_pxd = self.in_pxd, api = self.api)
if entry is not None:
entry.directive_locals = copy.copy(self.directive_locals)
else:
if self.directive_locals:
error(self.pos, "Decorators can only be followed by functions")
if self.in_pxd and self.visibility != 'extern':
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, api=self.api, is_cdef=1)
cname = cname, visibility = visibility,
in_pxd = self.in_pxd, api = self.api, is_cdef = 1)
class CStructOrUnionDefNode(StatNode):
......@@ -1700,9 +1698,8 @@ class CFuncDefNode(FuncDefNode):
cname = name_declarator.cname
self.entry = env.declare_cfunction(
name, type, self.pos,
cname = cname, visibility = self.visibility,
defining = self.body is not None,
api = self.api, modifiers = self.modifiers)
cname = cname, visibility = self.visibility, api = self.api,
defining = self.body is not None, modifiers = self.modifiers)
self.entry.inline_func_in_pxd = self.inline_in_pxd
self.return_type = type.return_type
if self.return_type.is_array and visibility != 'extern':
......
......@@ -507,10 +507,11 @@ class Scope(object):
return entry
def declare_var(self, name, type, pos,
cname = None, visibility = 'private', api = 0, is_cdef = 0):
cname = None, visibility = 'private',
api = 0, in_pxd = 0, is_cdef = 0):
# Add an entry for a variable.
if not cname:
if visibility != 'private':
if visibility != 'private' or api:
cname = name
else:
cname = self.mangle(Naming.var_prefix, name)
......@@ -520,7 +521,12 @@ class Scope(object):
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
if in_pxd and visibility != 'extern':
entry.defined_in_pxd = 1
entry.used = 1
if api:
entry.api = 1
entry.used = 1
self.control_flow.set_state((), (name, 'initialized'), False)
return entry
......@@ -578,12 +584,11 @@ class Scope(object):
self.pyfunc_entries.append(entry)
def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'private', defining = 0,
api = 0, in_pxd = 0, modifiers = (), utility_code = None):
cname = None, visibility = 'private', api = 0, in_pxd = 0,
defining = 0, modifiers = (), utility_code = None):
# Add an entry for a C function.
if not cname:
if (visibility == 'extern' or
visibility == 'public'and defining):
if visibility != 'private' or api:
cname = name
else:
cname = self.mangle(Naming.func_prefix, name)
......@@ -613,8 +618,6 @@ class Scope(object):
entry.type = type
else:
error(pos, "Function signature does not match previous declaration")
entry.cname = cname
entry.func_cname = cname
else:
entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
entry.func_cname = cname
......@@ -1027,13 +1030,12 @@ class ModuleScope(Scope):
return entry
def declare_var(self, name, type, pos,
cname = None, visibility = 'private', api = 0, is_cdef = 0):
cname = None, visibility = 'private',
api = 0, in_pxd = 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=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:
......@@ -1042,12 +1044,66 @@ class ModuleScope(Scope):
if not (type.is_pyobject and not type.is_extension_type):
raise InternalError(
"Non-cdef global variable is not a generic Python object")
entry.is_pyglobal = 1
if not cname:
defining = not in_pxd
if (visibility == 'extern' or (visibility == 'public' and defining)):
cname = name
else:
cname = self.mangle(Naming.var_prefix, name)
entry = self.lookup_here(name)
if entry and entry.defined_in_pxd:
#if visibility != 'private' and visibility != entry.visibility:
# warning(pos, "Variable '%s' previously declared as '%s'" % (name, entry.visibility), 1)
if not entry.type.same_as(type):
if visibility == 'extern' and entry.visibility == 'extern':
warning(pos, "Variable '%s' type does not match previous declaration" % name, 1)
entry.type = type
#else:
# error(pos, "Variable '%s' type does not match previous declaration" % name)
if entry.visibility != "private":
mangled_cname = self.mangle(Naming.var_prefix, name)
if entry.cname == mangled_cname:
cname = name
entry.cname = name
if not entry.is_implemented:
entry.is_implemented = True
return entry
entry = Scope.declare_var(self, name, type, pos,
cname=cname, visibility=visibility,
api=api, in_pxd=in_pxd, is_cdef=is_cdef)
if is_cdef:
entry.is_cglobal = 1
if entry.type.is_pyobject:
entry.init = 0
self.var_entries.append(entry)
else:
entry.is_pyglobal = 1
return entry
def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'private', api = 0, in_pxd = 0,
defining = 0, modifiers = (), utility_code = None):
# Add an entry for a C function.
if not cname:
if (visibility == 'extern' or (visibility == 'public' and defining)):
cname = name
else:
cname = self.mangle(Naming.func_prefix, name)
entry = self.lookup_here(name)
if entry and entry.defined_in_pxd:
if entry.visibility != "private":
mangled_cname = self.mangle(Naming.var_prefix, name)
if entry.cname == mangled_cname:
cname = name
entry.cname = cname
entry.func_cname = cname
entry = Scope.declare_cfunction(
self, name, type, pos,
cname = cname, visibility = visibility, api = api, in_pxd = in_pxd,
defining = defining, modifiers = modifiers, utility_code = utility_code)
return entry
def declare_global(self, name, pos):
......@@ -1315,12 +1371,14 @@ class LocalScope(Scope):
return entry
def declare_var(self, name, type, pos,
cname = None, visibility = 'private', api = 0, is_cdef = 0):
cname = None, visibility = 'private',
api = 0, in_pxd = 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=cname, visibility=visibility, api=api, is_cdef=is_cdef)
cname=cname, visibility=visibility,
api=api, in_pxd=in_pxd, 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
......@@ -1397,7 +1455,8 @@ class GeneratorExpressionScope(Scope):
return '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(prefix, name))
def declare_var(self, name, type, pos,
cname = None, visibility = 'private', api = 0, is_cdef = True):
cname = None, visibility = 'private',
api = 0, in_pxd = 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)
......@@ -1446,7 +1505,9 @@ class StructOrUnionScope(Scope):
Scope.__init__(self, name, None, None)
def declare_var(self, name, type, pos,
cname = None, visibility = 'private', api = 0, is_cdef = 0, allow_pyobject = 0):
cname = None, visibility = 'private',
api = 0, in_pxd = 0, is_cdef = 0,
allow_pyobject = 0):
# Add an entry for an attribute.
if not cname:
cname = name
......@@ -1466,8 +1527,8 @@ class StructOrUnionScope(Scope):
return entry
def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'private', defining = 0,
api = 0, in_pxd = 0, modifiers = ()): # currently no utility code ...
cname = None, visibility = 'private', api = 0, in_pxd = 0,
defining = 0, modifiers = ()): # currently no utility code ...
return self.declare_var(name, type, pos,
cname=cname, visibility=visibility)
......@@ -1513,12 +1574,14 @@ class PyClassScope(ClassScope):
is_py_class_scope = 1
def declare_var(self, name, type, pos,
cname = None, visibility = 'private', api = 0, is_cdef = 0):
cname = None, visibility = 'private',
api = 0, in_pxd = 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=cname, visibility=visibility, api=api, is_cdef=is_cdef)
cname=cname, visibility=visibility,
api=api, in_pxd=in_pxd, is_cdef=is_cdef)
entry.is_pyglobal = 1 # FIXME: WTF?
entry.is_pyclass_attr = 1
return entry
......@@ -1577,7 +1640,8 @@ class CClassScope(ClassScope):
self.parent_type.base_type.scope.needs_gc())
def declare_var(self, name, type, pos,
cname = None, visibility = 'private', api = 0, is_cdef = 0):
cname = None, visibility = 'private',
api = 0, in_pxd = 0, is_cdef = 0):
if is_cdef:
# Add an entry for an attribute.
if self.defined:
......@@ -1623,7 +1687,8 @@ class CClassScope(ClassScope):
type = py_object_type
# Add an entry for a class attribute.
entry = Scope.declare_var(self, name, type, pos,
cname=cname, visibility=visibility, api=api, is_cdef=is_cdef)
cname=cname, visibility=visibility,
api=api, in_pxd=in_pxd, 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
......@@ -1660,9 +1725,8 @@ class CClassScope(ClassScope):
return ClassScope.lookup_here(self, name)
def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'private',
defining = 0, api = 0, in_pxd = 0, modifiers = (),
utility_code = None):
cname = None, visibility = 'private', api = 0, in_pxd = 0,
defining = 0, modifiers = (), utility_code = None):
if get_special_method_signature(name):
error(pos, "Special methods must be declared with 'def', not 'cdef'")
args = type.args
......@@ -1765,8 +1829,9 @@ class CppClassScope(Scope):
self.inherited_var_entries = []
def declare_var(self, name, type, pos,
cname = None, visibility = 'extern', api = 0,
is_cdef = 0, allow_pyobject = 0):
cname = None, visibility = 'extern',
api = 0, in_pxd = 0, is_cdef = 0,
allow_pyobject = 0):
# Add an entry for an attribute.
if not cname:
cname = name
......@@ -1807,9 +1872,9 @@ class CppClassScope(Scope):
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', api = 0, defining = 0,
in_pxd = 0, modifiers = (), utility_code = None):
def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'extern', api = 0, in_pxd = 0,
defining = 0, modifiers = (), utility_code = None):
if name == self.name.split('::')[-1] and cname is None:
self.check_base_default_constructor(pos)
name = '<init>'
......
PYTHON setup.py build_ext --inplace
PYTHON test.py
######## setup.py ########
from Cython.Build.Dependencies import cythonize
from distutils.core import setup
exts = cythonize("*.pyx")
for e in exts:
if e.name == "d":
e.sources.append("a.c")
setup(
ext_modules = exts,
)
######## a.pxd ########
ctypedef api float flt
cdef int int0
cdef float flt0
cdef api int int1
cdef api float flt1
cdef public api int int2
cdef public api flt flt2
######## a.pyx ########
cdef int int0 = 1, int1 = 1, int2 = 1
cdef float flt0 = 1, flt1 = 1, flt2 = 1
cdef api int int3 = 1
cdef api flt flt3 = 1
cdef public int int4 = 1
cdef public flt flt4 = 1
def get_int():
return (int0, int1, int2, int3, int4)
def get_flt():
return (flt0, flt1, flt2, flt3, flt4)
######## b.pyx ########
from a cimport *
int0 = int1 = int2 = 7
flt0 = flt1 = flt2 = 7
######## c.pyx ########
# distutils: language = c++
cdef extern from "a_api.h":
int import_a() except -1
ctypedef float flt
int int1, int2, int3
flt flt1, flt2, flt3
import_a()
int1 = int2 = int3 = 5
flt1 = flt2 = flt3 = 5
######## inita.h ########
#if PY_MAJOR_VERSION >= 3
void inita(void)
{
PyObject *sys_modules = NULL;
PyObject *mod = NULL;
sys_modules = PyImport_GetModuleDict();
if (!sys_modules) return;
mod = PyInit_a();
if (!mod) return;
PyDict_SetItemString(sys_modules, (char*)"a", mod);
}
#endif
######## d.pyx ########
cdef extern from "a.h":
pass
cdef extern from "inita.h":
pass
cdef extern from "a.h":
void inita() except *
ctypedef float flt
int int2, int4
flt flt2, flt4
inita()
int2 = int4 = 3
flt2 = flt4 = 3
######## test.py ########
import a
assert a.get_int() == (1,1,1,1,1)
assert a.get_flt() == (1,1,1,1,1)
import b
assert a.get_int() == (7,7,7,1,1)
assert a.get_flt() == (7,7,7,1,1)
import c
assert a.get_int() == (7,5,5,5,1)
assert a.get_flt() == (7,5,5,5,1)
import d
import a
assert a.get_int() == (1,1,3,1,3)
assert a.get_flt() == (1,1,3,1,3)
# mode: compile
from publicapi_pxd_mix cimport *
bar0()
bar1()
bar2()
bar3()
spam0(None)
spam1(None)
spam2(None)
spam3(None)
i0 = 0
i1 = 1
i2 = 2
i3 = 3
......@@ -66,8 +66,9 @@ cdef public api void* spam3(object o) except NULL with gil
# --
#cdef public int i1
#cdef api int i2
#cdef public api int i3
cdef int i0 = 0 # XXX implement initialization!!!
cdef public int i1
cdef api int i2
cdef public api int i3
# --
......@@ -17,3 +17,8 @@ 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) nogil except NULL: return NULL
cdef public api void* spam3(object o) except NULL with gil: return NULL
cdef int i0 = 0 # XXX This should not be required!
cdef public int i1 = 1
cdef api int i2 = 2
cdef public api int i3 = 3
......@@ -2,6 +2,10 @@ __doc__ = u"""
>>> import sys
>>> sys.getrefcount(Foo.__pyx_vtable__)
2
>>> sys.getrefcount(__pyx_capi__['bar'])
2
>>> sys.getrefcount(__pyx_capi__['spam'])
2
>>> sys.getrefcount(__pyx_capi__['ten'])
2
>>> sys.getrefcount(__pyx_capi__['pi'])
......@@ -10,6 +14,8 @@ __doc__ = u"""
2
>>> sys.getrefcount(__pyx_capi__['dct'])
2
>>> sys.getrefcount(__pyx_capi__['tpl'])
2
>>> sys.getrefcount(__pyx_capi__['one'])
2
>>> sys.getrefcount(__pyx_capi__['two'])
......@@ -22,6 +28,8 @@ cdef public api class Foo [type FooType, object FooObject]:
cdef void bar(self):
pass
cdef public api void bar():
pass
cdef api void spam():
pass
......@@ -30,6 +38,7 @@ 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
cdef public api tuple tpl = ()
cdef public api float one = 1
cdef public float two = 2
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