Commit 1b176d9a authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

merge

parents e84211b5 0493847c
...@@ -38,6 +38,7 @@ Options: ...@@ -38,6 +38,7 @@ Options:
-a, --annotate Produce a colorized HTML version of the source. -a, --annotate Produce a colorized HTML version of the source.
--line-directives Produce #line directives pointing to the .pyx source --line-directives Produce #line directives pointing to the .pyx source
--cplus Output a c++ rather than c file. --cplus Output a c++ rather than c file.
--embed Embed the Python interpreter in a main() method.
--directive <name>=<value>[,<name=value,...] Overrides a compiler directive --directive <name>=<value>[,<name=value,...] Overrides a compiler directive
""" """
...@@ -89,6 +90,8 @@ def parse_command_line(args): ...@@ -89,6 +90,8 @@ def parse_command_line(args):
options.obj_only = 0 options.obj_only = 0
elif option in ("-+", "--cplus"): elif option in ("-+", "--cplus"):
options.cplus = 1 options.cplus = 1
elif option == "--embed":
Options.embed = True
elif option.startswith("-I"): elif option.startswith("-I"):
options.include_path.append(get_param(option)) options.include_path.append(get_param(option))
elif option == "--include-dir": elif option == "--include-dir":
......
...@@ -56,6 +56,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -56,6 +56,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else: else:
env.doc = self.doc env.doc = self.doc
env.directives = self.directives env.directives = self.directives
if Options.embed:
self.__main__cname = env.intern_identifier(EncodedString("__main__"))
self.body.analyse_declarations(env) self.body.analyse_declarations(env)
def process_implementation(self, options, result): def process_implementation(self, options, result):
...@@ -275,6 +277,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -275,6 +277,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.generate_module_init_func(modules[:-1], env, code) self.generate_module_init_func(modules[:-1], env, code)
code.mark_pos(None) code.mark_pos(None)
self.generate_module_cleanup_func(env, code) self.generate_module_cleanup_func(env, code)
if Options.embed:
self.generate_main_method(env, code)
self.generate_filename_table(code) self.generate_filename_table(code)
self.generate_utility_functions(env, code, h_code) self.generate_utility_functions(env, code, h_code)
...@@ -651,9 +655,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -651,9 +655,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type = entry.type type = entry.type
scope = type.scope scope = type.scope
if scope: if scope:
kind = type.kind
packed = type.is_struct and type.packed
if packed:
kind = "%s %s" % (type.kind, "__Pyx_PACKED")
code.globalstate.use_utility_code(packed_struct_utility_code)
header, footer = \ header, footer = \
self.sue_header_footer(type, type.kind, type.cname) self.sue_header_footer(type, kind, type.cname)
code.putln("") code.putln("")
if packed:
code.putln("#if !defined(__GNUC__)")
code.putln("#pragma pack(push, 1)")
code.putln("#endif")
code.putln(header) code.putln(header)
var_entries = scope.var_entries var_entries = scope.var_entries
if not var_entries: if not var_entries:
...@@ -665,6 +678,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -665,6 +678,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"%s;" % "%s;" %
attr.type.declaration_code(attr.cname)) attr.type.declaration_code(attr.cname))
code.putln(footer) code.putln(footer)
if packed:
code.putln("#if !defined(__GNUC__)")
code.putln("#pragma pack(pop)")
code.putln("#endif")
def generate_enum_definition(self, entry, code): def generate_enum_definition(self, entry, code):
code.mark_pos(entry.pos) code.mark_pos(entry.pos)
...@@ -1734,6 +1751,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1734,6 +1751,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("Py_INCREF(Py_None); return Py_None;") code.putln("Py_INCREF(Py_None); return Py_None;")
code.putln('}') code.putln('}')
def generate_main_method(self, env, code):
code.globalstate.use_utility_code(main_method.specialize(module_name=env.module_name))
def generate_filename_init_call(self, code): def generate_filename_init_call(self, code):
code.putln("%s();" % Naming.fileinit_cname) code.putln("%s();" % Naming.fileinit_cname)
...@@ -1798,6 +1818,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1798,6 +1818,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
env.module_cname, env.module_cname,
Naming.builtins_cname, Naming.builtins_cname,
code.error_goto(self.pos))) code.error_goto(self.pos)))
if Options.embed:
code.putln(
'if (__Pyx_SetAttrString(%s, "__name__", %s) < 0) %s;' % (
env.module_cname,
self.__main__cname,
code.error_goto(self.pos)))
if Options.pre_import is not None: if Options.pre_import is not None:
code.putln( code.putln(
'%s = PyImport_AddModule(__Pyx_NAMESTR("%s"));' % ( '%s = PyImport_AddModule(__Pyx_NAMESTR("%s"));' % (
...@@ -2442,3 +2468,35 @@ static __Pyx_RefnannyAPIStruct *__Pyx_Refnanny = NULL; ...@@ -2442,3 +2468,35 @@ static __Pyx_RefnannyAPIStruct *__Pyx_Refnanny = NULL;
#define __Pyx_XGIVEREF(r) if((r) == NULL) ; else __Pyx_GIVEREF(r) #define __Pyx_XGIVEREF(r) if((r) == NULL) ; else __Pyx_GIVEREF(r)
#define __Pyx_XGOTREF(r) if((r) == NULL) ; else __Pyx_GOTREF(r) #define __Pyx_XGOTREF(r) if((r) == NULL) ; else __Pyx_GOTREF(r)
""") """)
main_method = UtilityCode(
impl = """
int main(int argc, char** argv) {
int r = 0;
PyObject* m = NULL;
Py_SetProgramName(argv[0]);
Py_Initialize();
PySys_SetArgv(argc, argv);
#if PY_MAJOR_VERSION < 3
init%(module_name)s();
#else
m = PyInit_%(module_name)s(name);
#endif
if (PyErr_Occurred() != NULL) {
r = 1;
PyErr_Print(); /* This exits with the right code if SystemExit. */
if (Py_FlushLine()) PyErr_Clear();
}
Py_XDECREF(m);
Py_Finalize();
return r;
}
""")
packed_struct_utility_code = UtilityCode(proto="""
#if defined(__GNUC__)
#define __Pyx_PACKED __attribute__((__packed__))
#else
#define __Pyx_PACKED
#endif
""", impl="")
...@@ -840,16 +840,19 @@ class CStructOrUnionDefNode(StatNode): ...@@ -840,16 +840,19 @@ class CStructOrUnionDefNode(StatNode):
# in_pxd boolean # in_pxd boolean
# attributes [CVarDefNode] or None # attributes [CVarDefNode] or None
# entry Entry # entry Entry
# packed boolean
child_attrs = ["attributes"] child_attrs = ["attributes"]
def analyse_declarations(self, env): def analyse_declarations(self, env):
scope = None scope = None
if self.visibility == 'extern' and self.packed:
error(self.pos, "Cannot declare extern struct as 'packed'")
if self.attributes is not None: if self.attributes is not None:
scope = StructOrUnionScope(self.name) scope = StructOrUnionScope(self.name)
self.entry = env.declare_struct_or_union( self.entry = env.declare_struct_or_union(
self.name, self.kind, scope, self.typedef_flag, self.pos, self.name, self.kind, scope, self.typedef_flag, self.pos,
self.cname, visibility = self.visibility) self.cname, visibility = self.visibility, packed = self.packed)
if self.attributes is not None: if self.attributes is not None:
if self.in_pxd and not env.in_cinclude: if self.in_pxd and not env.in_cinclude:
self.entry.defined_in_pxd = 1 self.entry.defined_in_pxd = 1
......
...@@ -53,6 +53,11 @@ optimize_simple_methods = 1 ...@@ -53,6 +53,11 @@ optimize_simple_methods = 1
# Append the c file and line number to the traceback for exceptions. # Append the c file and line number to the traceback for exceptions.
c_line_in_traceback = 1 c_line_in_traceback = 1
# Whether or not to embed the Python interpreter, for use in making a
# standalone executable. This will provide a main() method which simply
# executes the body of this module.
embed = False
# Declare pragmas # Declare pragmas
option_defaults = { option_defaults = {
......
...@@ -2078,7 +2078,7 @@ def p_cdef_statement(s, ctx): ...@@ -2078,7 +2078,7 @@ def p_cdef_statement(s, ctx):
#if ctx.api: #if ctx.api:
# error(pos, "'api' not allowed with extension class") # error(pos, "'api' not allowed with extension class")
return p_c_class_definition(s, pos, ctx) return p_c_class_definition(s, pos, ctx)
elif s.sy == 'IDENT' and s.systring in struct_union_or_enum: elif s.sy == 'IDENT' and s.systring in ("struct", "union", "enum", "packed"):
if ctx.level not in ('module', 'module_pxd'): if ctx.level not in ('module', 'module_pxd'):
error(pos, "C struct/union/enum definition not allowed here") error(pos, "C struct/union/enum definition not allowed here")
#if ctx.visibility == 'public': #if ctx.visibility == 'public':
...@@ -2114,10 +2114,6 @@ def p_cdef_extern_block(s, pos, ctx): ...@@ -2114,10 +2114,6 @@ def p_cdef_extern_block(s, pos, ctx):
include_file = include_file, include_file = include_file,
body = body) body = body)
struct_union_or_enum = (
"struct", "union", "enum"
)
def p_c_enum_definition(s, pos, ctx): def p_c_enum_definition(s, pos, ctx):
# s.sy == ident 'enum' # s.sy == ident 'enum'
s.next() s.next()
...@@ -2168,6 +2164,12 @@ def p_c_enum_item(s, items): ...@@ -2168,6 +2164,12 @@ def p_c_enum_item(s, items):
name = name, cname = cname, value = value)) name = name, cname = cname, value = value))
def p_c_struct_or_union_definition(s, pos, ctx): def p_c_struct_or_union_definition(s, pos, ctx):
packed = False
if s.systring == 'packed':
packed = True
s.next()
if s.sy != 'IDENT' or s.systring != 'struct':
s.expected('struct')
# s.sy == ident 'struct' or 'union' # s.sy == ident 'struct' or 'union'
kind = s.systring kind = s.systring
s.next() s.next()
...@@ -2193,7 +2195,7 @@ def p_c_struct_or_union_definition(s, pos, ctx): ...@@ -2193,7 +2195,7 @@ def p_c_struct_or_union_definition(s, pos, ctx):
return Nodes.CStructOrUnionDefNode(pos, return Nodes.CStructOrUnionDefNode(pos,
name = name, cname = cname, kind = kind, attributes = attributes, name = name, cname = cname, kind = kind, attributes = attributes,
typedef_flag = ctx.typedef_flag, visibility = ctx.visibility, typedef_flag = ctx.typedef_flag, visibility = ctx.visibility,
in_pxd = ctx.level == 'module_pxd') in_pxd = ctx.level == 'module_pxd', packed = packed)
def p_visibility(s, prev_visibility): def p_visibility(s, prev_visibility):
pos = s.position() pos = s.position()
...@@ -2265,7 +2267,7 @@ def p_ctypedef_statement(s, ctx): ...@@ -2265,7 +2267,7 @@ def p_ctypedef_statement(s, ctx):
ctx.api = 1 ctx.api = 1
if s.sy == 'class': if s.sy == 'class':
return p_c_class_definition(s, pos, ctx) return p_c_class_definition(s, pos, ctx)
elif s.sy == 'IDENT' and s.systring in ('struct', 'union', 'enum'): elif s.sy == 'IDENT' and s.systring in ('packed', 'struct', 'union', 'enum'):
if s.systring == 'enum': if s.systring == 'enum':
return p_c_enum_definition(s, pos, ctx) return p_c_enum_definition(s, pos, ctx)
else: else:
......
...@@ -1023,11 +1023,12 @@ class CStructOrUnionType(CType): ...@@ -1023,11 +1023,12 @@ class CStructOrUnionType(CType):
# kind string "struct" or "union" # kind string "struct" or "union"
# scope StructOrUnionScope, or None if incomplete # scope StructOrUnionScope, or None if incomplete
# typedef_flag boolean # typedef_flag boolean
# packed boolean
is_struct_or_union = 1 is_struct_or_union = 1
has_attributes = 1 has_attributes = 1
def __init__(self, name, kind, scope, typedef_flag, cname): def __init__(self, name, kind, scope, typedef_flag, cname, packed=False):
self.name = name self.name = name
self.cname = cname self.cname = cname
self.kind = kind self.kind = kind
...@@ -1038,6 +1039,7 @@ class CStructOrUnionType(CType): ...@@ -1038,6 +1039,7 @@ class CStructOrUnionType(CType):
self.to_py_function = "%s_to_py_%s" % (Naming.convert_func_prefix, self.cname) self.to_py_function = "%s_to_py_%s" % (Naming.convert_func_prefix, self.cname)
self.exception_check = True self.exception_check = True
self._convert_code = None self._convert_code = None
self.packed = packed
def create_convert_utility_code(self, env): def create_convert_utility_code(self, env):
if env.outer_scope is None: if env.outer_scope is None:
......
...@@ -466,7 +466,7 @@ class PyrexScanner(Scanner): ...@@ -466,7 +466,7 @@ class PyrexScanner(Scanner):
else: else:
self.expected(what, message) self.expected(what, message)
def expected(self, what, message): def expected(self, what, message = None):
if message: if message:
self.error(message) self.error(message)
else: else:
......
...@@ -353,7 +353,8 @@ class Scope(object): ...@@ -353,7 +353,8 @@ class Scope(object):
return entry return entry
def declare_struct_or_union(self, name, kind, scope, def declare_struct_or_union(self, name, kind, scope,
typedef_flag, pos, cname = None, visibility = 'private'): typedef_flag, pos, cname = None, visibility = 'private',
packed = False):
# Add an entry for a struct or union definition. # Add an entry for a struct or union definition.
if not cname: if not cname:
if self.in_cinclude or visibility == 'public': if self.in_cinclude or visibility == 'public':
...@@ -363,7 +364,7 @@ class Scope(object): ...@@ -363,7 +364,7 @@ class Scope(object):
entry = self.lookup_here(name) entry = self.lookup_here(name)
if not entry: if not entry:
type = PyrexTypes.CStructOrUnionType( type = PyrexTypes.CStructOrUnionType(
name, kind, scope, typedef_flag, cname) name, kind, scope, typedef_flag, cname, packed)
entry = self.declare_type(name, type, pos, cname, entry = self.declare_type(name, type, pos, cname,
visibility = visibility, defining = scope is not None) visibility = visibility, defining = scope is not None)
self.sue_entries.append(entry) self.sue_entries.append(entry)
......
PYVERSION = 2.2 # Makefile for creating our standalone Cython program
PYHOME = $(HOME)/pkg/python/$(PYVERSION) PYVERSION=2.3
PYARCH = $(PYHOME)/$(ARCH) PYPREFIX=/usr
PYINCLUDE = \ INCLUDES=-I$(PYPREFIX)/include/python$(PYVERSION)
-I$(PYHOME)/include/python$(PYVERSION) \
-I$(PYARCH)/include/python$(PYVERSION) embedded: embedded.o
PYLIB = -L$(PYARCH)/lib/python$(PYVERSION)/config \ gcc -o $@ $^ -lpython$(PYVERSION)
-lpython$(PYVERSION) \
-ldl -lpthread -lutil -lm
%.c: %.pyx embedded.o: embedded.c
../../bin/cython $< gcc -c $^ $(INCLUDES)
%.o: %.c embedded.c: embedded.pyx
gcc -c -fPIC $(PYINCLUDE) $< @python ../../cython.py --embed embedded.pyx
#%.so: %.o all: embedded
# gcc -shared $< -lm -o $@
all: main
main: main.o embedded.o
gcc main.o embedded.o $(PYLIB) -o main
clean: clean:
@echo Cleaning Demos/embed @echo Cleaning Demos/embed
@rm -f *~ *.o *.so core core.* embedded.h embedded.c main @rm -f *~ *.o *.so core core.* *.c embedded
embedded.h: embedded.c
main.o: embedded.h
PYVERSION = 2.2 # Makefile for creating our standalone Cython program
PYHOME = $(HOME)/pkg/python/$(PYVERSION) PYVERSION=2.3
PYARCH = $(PYHOME)/$(ARCH) PYPREFIX=/usr
PYINCLUDE = \ INCLUDES=-I$(PYPREFIX)/include/python$(PYVERSION)
-I$(PYHOME)/include/python$(PYVERSION) \
-I$(PYARCH)/include/python$(PYVERSION) embedded: embedded.o
PYLIB = -L$(PYARCH)/lib/python$(PYVERSION)/config \ gcc -o $@ $^ -lpython$(PYVERSION)
-lpython$(PYVERSION) \
-ldl -lpthread -lutil -lm
%.c: %.pyx embedded.o: embedded.c
../../bin/cython $< gcc -c $^ $(INCLUDES)
%.o: %.c embedded.c: embedded.pyx
gcc -c -fPIC $(PYINCLUDE) $< @python ../../cython.py --embed embedded.pyx
#%.so: %.o all: embedded
# gcc -shared $< -lm -o $@
all: main
main: main.o embedded.o
gcc main.o embedded.o $(PYLIB) -o main
clean: clean:
@echo Cleaning Demos/embed @echo Cleaning Demos/embed
@rm -f *~ *.o *.so core core.* embedded.h embedded.c main @rm -f *~ *.o *.so core core.* *.c embedded
embedded.h: embedded.c
main.o: embedded.h
cdef public void spam():
praise()
def praise(): print __name__
print "Spam, glorious spam!"
if __name__ == "__main__":
print "Hi, I'm embedded."
else:
print "I'm being imported."
cdef packed foo:
pass
_ERRORS = u"""
1:12: Expected 'struct'
"""
cdef extern:
cdef packed struct MyStruct:
char a
_ERRORS = u"""
2:9: Cannot declare extern struct as 'packed'
"""
"""
>>> f()
(9, 9)
"""
cdef packed struct MyCdefStruct:
char a
double b
ctypedef packed struct MyCTypeDefStruct:
char a
double b
def f():
return (sizeof(MyCdefStruct), sizeof(MyCTypeDefStruct))
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