Commit 0a56c99d authored by Lisandro Dalcin's avatar Lisandro Dalcin

public/capi: fixes and cleanups, implement exporting cdef variables

parent b5037005
This diff is collapsed.
......@@ -970,7 +970,7 @@ class CVarDefNode(StatNode):
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
......@@ -980,6 +980,7 @@ class CStructOrUnionDefNode(StatNode):
# kind "struct" or "union"
# typedef_flag boolean
# visibility "public" or "private"
# api boolean
# in_pxd boolean
# attributes [CVarDefNode] or None
# entry Entry
......@@ -995,7 +996,8 @@ class CStructOrUnionDefNode(StatNode):
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
......@@ -1078,15 +1080,16 @@ class CEnumDefNode(StatNode):
# 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
......@@ -1097,7 +1100,7 @@ class CEnumDefNode(StatNode):
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" % (
......@@ -1127,9 +1130,9 @@ class CEnumDefItemNode(StatNode):
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)
......@@ -1137,6 +1140,7 @@ class CTypeDefNode(StatNode):
# base_type CBaseTypeNode
# declarator CDeclaratorNode
# visibility "public" or "private"
# api boolean
# in_pxd boolean
child_attrs = ["base_type", "declarator"]
......@@ -1147,10 +1151,10 @@ class CTypeDefNode(StatNode):
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):
......@@ -1740,7 +1744,6 @@ class CFuncDefNode(FuncDefNode):
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:
......@@ -1754,24 +1757,20 @@ class CFuncDefNode(FuncDefNode):
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:
......
......@@ -2420,7 +2420,7 @@ def p_c_enum_definition(s, pos, ctx):
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':
......@@ -2478,10 +2478,10 @@ def p_c_struct_or_union_definition(s, pos, ctx):
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()
......@@ -2566,7 +2566,8 @@ def p_ctypedef_statement(s, ctx):
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):
......@@ -2693,8 +2694,8 @@ def p_c_class_definition(s, pos, ctx):
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':
......@@ -2718,7 +2719,10 @@ def p_c_class_definition(s, pos, ctx):
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,
......
......@@ -1190,8 +1190,8 @@ class CComplexType(CNumericType):
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),
......
This diff is collapsed.
......@@ -11,6 +11,12 @@ cdef public class C[type C_Type, object C_Obj]:
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
......
# --
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)
# --
# --
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
# --
# --
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)
# --
# --
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
# --
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
......@@ -2,8 +2,20 @@ __doc__ = u"""
>>> 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]:
......@@ -12,3 +24,12 @@ 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
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