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 ...@@ -8,6 +8,7 @@ Cython/Runtime/refnanny.c
BUILD/ BUILD/
build/ build/
!tests/build/
dist/ dist/
.gitrev .gitrev
.coverage .coverage
......
...@@ -1166,39 +1166,19 @@ class CCodeWriter(object): ...@@ -1166,39 +1166,19 @@ class CCodeWriter(object):
self.funcstate.use_label(lbl) self.funcstate.use_label(lbl)
self.putln("goto %s;" % lbl) self.putln("goto %s;" % lbl)
def put_var_declarations(self, entries, static = 0, dll_linkage = None, def put_var_declaration(self, entry, storage_class="",
definition = True): 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):
#print "Code.put_var_declaration:", entry.name, "definition =", definition ### #print "Code.put_var_declaration:", entry.name, "definition =", definition ###
if entry.in_closure: if entry.visibility == 'private' and not (definition or entry.defined_in_pxd):
return #print "...private and not definition, skipping", entry.cname ###
visibility = entry.visibility
if visibility == 'private' and not definition:
#print "...private and not definition, skipping" ###
return return
if not entry.used and visibility == "private": if entry.visibility == "private" and not entry.used:
#print "not used and private, skipping", entry.cname ### #print "...private and not used, skipping", entry.cname ###
return 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: if storage_class:
self.put("%s " % storage_class) self.put("%s " % storage_class)
if visibility != 'public': self.put(entry.type.declaration_code(
dll_linkage = None entry.cname, dll_linkage = dll_linkage))
self.put(entry.type.declaration_code(entry.cname,
dll_linkage = dll_linkage))
if entry.init is not None: if entry.init is not None:
self.put_safe(" = %s" % entry.type.literal_code(entry.init)) self.put_safe(" = %s" % entry.type.literal_code(entry.init))
self.putln(";") self.putln(";")
......
This diff is collapsed.
...@@ -36,6 +36,7 @@ prop_set_prefix = pyrex_prefix + "setprop_" ...@@ -36,6 +36,7 @@ prop_set_prefix = pyrex_prefix + "setprop_"
type_prefix = pyrex_prefix + "t_" type_prefix = pyrex_prefix + "t_"
typeobj_prefix = pyrex_prefix + "type_" typeobj_prefix = pyrex_prefix + "type_"
var_prefix = pyrex_prefix + "v_" var_prefix = pyrex_prefix + "v_"
varptr_prefix = pyrex_prefix + "vp_"
wrapperbase_prefix= pyrex_prefix + "wrapperbase_" wrapperbase_prefix= pyrex_prefix + "wrapperbase_"
bufstruct_prefix = pyrex_prefix + "bstruct_" bufstruct_prefix = pyrex_prefix + "bstruct_"
bufstride_prefix = pyrex_prefix + "bstride_" bufstride_prefix = pyrex_prefix + "bstride_"
......
...@@ -969,18 +969,16 @@ class CVarDefNode(StatNode): ...@@ -969,18 +969,16 @@ class CVarDefNode(StatNode):
return return
if type.is_cfunction: if type.is_cfunction:
entry = dest_scope.declare_cfunction(name, type, declarator.pos, entry = dest_scope.declare_cfunction(name, type, declarator.pos,
cname = cname, visibility = self.visibility, in_pxd = self.in_pxd, cname = cname, visibility = self.visibility,
api = self.api) in_pxd = self.in_pxd, api = self.api)
if entry is not None: if entry is not None:
entry.directive_locals = copy.copy(self.directive_locals) entry.directive_locals = copy.copy(self.directive_locals)
else: else:
if self.directive_locals: if self.directive_locals:
error(self.pos, "Decorators can only be followed by functions") 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, 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): class CStructOrUnionDefNode(StatNode):
...@@ -1700,9 +1698,8 @@ class CFuncDefNode(FuncDefNode): ...@@ -1700,9 +1698,8 @@ class CFuncDefNode(FuncDefNode):
cname = name_declarator.cname cname = name_declarator.cname
self.entry = env.declare_cfunction( self.entry = env.declare_cfunction(
name, type, self.pos, name, type, self.pos,
cname = cname, visibility = self.visibility, cname = cname, visibility = self.visibility, api = self.api,
defining = self.body is not None, defining = self.body is not None, modifiers = self.modifiers)
api = self.api, modifiers = self.modifiers)
self.entry.inline_func_in_pxd = self.inline_in_pxd self.entry.inline_func_in_pxd = self.inline_in_pxd
self.return_type = type.return_type self.return_type = type.return_type
if self.return_type.is_array and visibility != 'extern': if self.return_type.is_array and visibility != 'extern':
......
This diff is collapsed.
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 # mode: compile
from publicapi_pxd_mix cimport * 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 ...@@ -66,8 +66,9 @@ cdef public api void* spam3(object o) except NULL with gil
# -- # --
#cdef public int i1 cdef int i0 = 0 # XXX implement initialization!!!
#cdef api int i2 cdef public int i1
#cdef public api int i3 cdef api int i2
cdef public api int i3
# -- # --
...@@ -17,3 +17,8 @@ cdef void* spam0(object o) except NULL: return NULL ...@@ -17,3 +17,8 @@ cdef void* spam0(object o) except NULL: return NULL
cdef public void* spam1(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 api void* spam2(object o) nogil except NULL: return NULL
cdef public api void* spam3(object o) except NULL with gil: 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""" ...@@ -2,6 +2,10 @@ __doc__ = u"""
>>> import sys >>> import sys
>>> sys.getrefcount(Foo.__pyx_vtable__) >>> sys.getrefcount(Foo.__pyx_vtable__)
2 2
>>> sys.getrefcount(__pyx_capi__['bar'])
2
>>> sys.getrefcount(__pyx_capi__['spam'])
2
>>> sys.getrefcount(__pyx_capi__['ten']) >>> sys.getrefcount(__pyx_capi__['ten'])
2 2
>>> sys.getrefcount(__pyx_capi__['pi']) >>> sys.getrefcount(__pyx_capi__['pi'])
...@@ -10,6 +14,8 @@ __doc__ = u""" ...@@ -10,6 +14,8 @@ __doc__ = u"""
2 2
>>> sys.getrefcount(__pyx_capi__['dct']) >>> sys.getrefcount(__pyx_capi__['dct'])
2 2
>>> sys.getrefcount(__pyx_capi__['tpl'])
2
>>> sys.getrefcount(__pyx_capi__['one']) >>> sys.getrefcount(__pyx_capi__['one'])
2 2
>>> sys.getrefcount(__pyx_capi__['two']) >>> sys.getrefcount(__pyx_capi__['two'])
...@@ -22,6 +28,8 @@ cdef public api class Foo [type FooType, object FooObject]: ...@@ -22,6 +28,8 @@ cdef public api class Foo [type FooType, object FooObject]:
cdef void bar(self): cdef void bar(self):
pass pass
cdef public api void bar():
pass
cdef api void spam(): cdef api void spam():
pass pass
...@@ -30,6 +38,7 @@ cdef api double pi = 3.14 ...@@ -30,6 +38,7 @@ cdef api double pi = 3.14
cdef api object obj = object() cdef api object obj = object()
cdef api dict dct = {} cdef api dict dct = {}
cdef public api int one = 1 cdef public api tuple tpl = ()
cdef public int two = 2 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