code.putln("#pragma pack(pop)")
code.putln("#endif")
+ def generate_cpp_class_definition(self, entry, code):
+ code.mark_pos(entry.pos)\r
+ type = entry.type\r
+ scope = type.scope\r
+ if scope:\r
+ kind = type.kind\r
+ packed = type.is_cpp_class and type.packed\r
+ if packed:\r
+ kind = "%s %s" % (type.kind, "__Pyx_PACKED")\r
+ code.globalstate.use_utility_code(packed_struct_utility_code)\r
+ header, footer = \\r
+ self.sue_header_footer(type, kind, type.cname)\r
+ code.putln("")\r
+ if packed:\r
+ code.putln("#if !defined(__GNUC__)")\r
+ code.putln("#pragma pack(push, 1)")\r
+ code.putln("#endif")\r
+ code.putln(header)\r
+ var_entries = scope.var_entries\r
+ for attr in var_entries:\r
+ code.putln(\r
+ "%s;" %\r
+ attr.type.declaration_code(attr.cname))\r
+ code.putln(footer)\r
+ if packed:\r
+ code.putln("#if !defined(__GNUC__)")\r
+ code.putln("#pragma pack(pop)")\r
+ code.putln("#endif")\r
+\r
def generate_enum_definition(self, entry, code):
code.mark_pos(entry.pos)
type = entry.type
# name string
# cname string or None
- # visibility "public" or "private"
+ # visibility "extern"\r
# in_pxd boolean
# attributes [CVarDefNode] or None
# entry Entry
+ # base_classes [string]
+ # namespace string or None\r
def analyse_declarations(self, env):
scope = None
if self.attributes is not None:
- scope = StructOrUnionScope(self.name) # for now
- self.entry = env.declare_struct_or_union(
- self.name, "struct", scope, 0, self.pos,
- self.cname, visibility = self.visibility)
+ scope = CppClassScope(self.name)\r
+ self.entry = env.declare_cpp_class(\r
+ self.name, "cppclass", scope, 0, self.pos,\r
+ self.cname, self.base_classes, self.namespace, visibility = self.visibility)\r
if self.attributes is not None:
if self.in_pxd and not env.in_cinclude:
self.entry.defined_in_pxd = 1
api = 0
overridable = 0
nogil = 0
+ namespace = None\r
def __init__(self, **kwds):
self.__dict__.update(kwds)
_, include_file = p_string_literal(s)
if s.systring == "namespace":
s.next()
- namespace = p_ident(s)
+ ctx.namespace = p_ident(s)\r
ctx = ctx(cdef_flag = 1, visibility = 'extern')
if p_nogil(s):
ctx.nogil = 1
full_module_name = full_module_name,
option_comments = option_comments)
-
-#Implementing...
-
def p_cpp_class_definition(s, pos, ctx):
# s.sy == 'cppclass'
s.next()
s.expect_newline("Syntax error in C++ class definition")
return Nodes.CppClassNode(pos,
name = class_name,
- namespace = None,
cname = None,
base_classes = base_classes,
+ namespace = ctx.namespace,\r
visibility = ctx.visibility,
in_pxd = ctx.level == 'module_pxd',
- attributes = None)
-
-def p_cpp_class(s):
- pass
+ attributes = attributes)\r
is_null_ptr = 0
is_cfunction = 0
is_struct_or_union = 0
+ is_cpp_class = 0\r
is_struct = 0
is_enum = 0
is_typedef = 0
for x in self.scope.var_entries]
return max(child_depths) + 1
+class CppClassType(CType):\r
+ # name string\r
+ # cname string\r
+ # kind string "cppclass"\r
+ # scope CppClassScope\r
+ # typedef_flag boolean\r
+ # packed boolean\r
+ \r
+ is_cpp_class = 1\r
+ has_attributes = 1\r
+ base_classes = []
+ namespace = None\r
+ \r
+ def __init__(self, name, kind, scope, typedef_flag, cname, base_classes,
+ namespace = None, packed=False):\r
+ self.name = name\r
+ self.cname = cname\r
+ self.kind = kind\r
+ self.scope = scope\r
+ self.typedef_flag = typedef_flag\r
+ self.exception_check = True\r
+ self._convert_code = None\r
+ self.packed = packed\r
+ self.base_classes = base_classes
+ self.namespace = namespace\r
+\r
+ def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
+ inherited = ""
+ for base_class in self.base_classes:
+ if inherited != "":
+ inherited += " : public "
+ inherited += base_class
+ if base_class != baseclasses[-1]:
+ inherited += " , "
+ return "%s%s" % (self.name, inherited)
+ \r
+\r
+ def is_subclass(self, other_type):\r
+ if not base_classes.empty():\r
+ for base_class in self.base_classes:\r
+ if base_class.is_subclass(other_type):\r
+ return 1\r
+ return 0\r
+\r
+ def assignable_from_resolved_type(self, other_type):\r
+ if self.same_as_resolved_type(other_type):\r
+ return 1\r
+ if self.is_subclass(other) or self.same_as(other_type):\r
+ return 1\r
+ return 0\r
+\r
class CEnumType(CType):
# name string
# cname string or None
self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
return entry
+ def declare_cpp_class(self, name, kind, scope,\r
+ typedef_flag, pos, cname = None, base_classes = [], namespace = None,
+ visibility = 'extern', packed = False):\r
+ if visibility != 'extern':\r
+ error(pos, "C++ classes may only be extern")\r
+ if not entry:\r
+ type = PyrexTypes.CppClassType(\r
+ name, kind, scope, typedef_flag, cname, base_classes, namespace, packed)\r
+ entry = self.declare_type(name, type, pos, cname,\r
+ visibility = visibility, defining = scope is not None)\r
+ self.sue_entries.append(entry)\r
+ else:\r
+ if not (entry.is_type and entry.type.is_cpp_class\r
+ and entry.type.kind == kind):\r
+ warning(pos, "'%s' redeclared " % name, 0)\r
+ elif scope and entry.type.scope:\r
+ warning(pos, "'%s' already defined (ignoring second definition)" % name, 0)\r
+ else:\r
+ self.check_previous_typedef_flag(entry, typedef_flag, pos)\r
+ if scope:\r
+ entry.type.scope = scope\r
+ self.type_entries.append(entry)\r
+ if not scope and not entry.type.scope:\r
+ self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)\r
+ return entry\r
+ \r
def check_previous_typedef_flag(self, entry, typedef_flag, pos):
if typedef_flag != entry.type.typedef_flag:
error(pos, "'%s' previously declared using '%s'" % (