self.generate_h_code(env, result)
def generate_h_code(self, env, result):
- public_vars_and_funcs = []
+ public_vars = []
+ public_funcs = []
public_extension_types = []
for entry in env.var_entries:
if entry.visibility == 'public':
- public_vars_and_funcs.append(entry)
+ public_vars.append(entry)
for entry in env.cfunc_entries:
if entry.visibility == 'public':
- public_vars_and_funcs.append(entry)
+ public_funcs.append(entry)
for entry in env.c_class_entries:
if entry.visibility == 'public':
public_extension_types.append(entry)
- if public_vars_and_funcs or public_extension_types:
+ if public_vars or public_funcs or public_extension_types:
result.h_file = replace_suffix(result.c_file, ".h")
result.i_file = replace_suffix(result.c_file, ".pxi")
h_code = Code.CCodeWriter(open_new_file(result.h_file))
i_code = Code.PyrexCodeWriter(result.i_file)
+ header_barrier = "__HAS_PYX_" + env.module_name
+ h_code.putln("#ifndef %s" % header_barrier)
+ h_code.putln("#define %s" % header_barrier)
self.generate_extern_c_macro_definition(h_code)
- for entry in public_vars_and_funcs:
+ for entry in public_vars:
h_code.putln("%s %s;" % (
Naming.extern_c_macro,
entry.type.declaration_code(
for entry in public_extension_types:
self.generate_cclass_header_code(entry.type, h_code)
self.generate_cclass_include_code(entry.type, i_code)
+ if public_funcs:
+ sort_public_funcs = [ (func.cname, func)
+ for func in public_funcs ]
+ sort_public_funcs.sort()
+ public_funcs = [ func[1] for func in sort_public_funcs ]
+ for entry in public_funcs:
+ h_code.putln(
+ 'static %s;' %
+ entry.type.declaration_code("(*%s)" % entry.cname))
+ i_code.putln("cdef extern %s" %
+ entry.type.declaration_code(entry.cname, pyrex = 1))
+ h_code.putln(
+ "static struct {char *s; void **p;} _%s_API[] = {" %
+ env.module_name)
+ for entry in public_funcs:
+ h_code.putln('{"%s", (void*)(&%s)},' % (
+ entry.cname, entry.cname))
+ h_code.putln("{0, 0}")
+ h_code.putln("};")
+ self.generate_c_api_import_code(env, h_code)
h_code.putln("PyMODINIT_FUNC init%s(void);" % env.module_name)
+ h_code.putln("#endif /* %s */" % header_barrier)
def generate_cclass_header_code(self, type, h_code):
#h_code.putln("extern DL_IMPORT(PyTypeObject) %s;" % type.typeobj_cname)
self.body.generate_function_definitions(env, code)
self.generate_interned_name_table(env, code)
self.generate_py_string_table(env, code)
+ self.generate_c_api_table(env, code)
self.generate_typeobj_definitions(env, code)
self.generate_method_table(env, code)
self.generate_filename_init_prototype(code)
entry.type.typeptr_cname)
code.put_var_declarations(env.var_entries, static = 1,
dll_linkage = "DL_EXPORT", definition = definition)
- code.put_var_declarations(env.default_entries, static = 1)
+ code.put_var_declarations(env.default_entries, static = 1,
+ definition = definition)
def generate_cfunction_predeclarations(self, env, code):
for entry in env.cfunc_entries:
dll_linkage = None
header = entry.type.declaration_code(entry.cname,
dll_linkage = dll_linkage)
- if entry.visibility <> 'private':
+ if entry.visibility == 'private':
+ storage_class = "static "
+ elif entry.visibility == 'extern':
storage_class = "%s " % Naming.extern_c_macro
else:
- storage_class = "static "
+ storage_class = ""
code.putln("%s%s; /*proto*/" % (
storage_class,
header))
code.putln(
"};")
+ def generate_c_api_table(self, env, code):
+ public_funcs = []
+ for entry in env.cfunc_entries:
+ if entry.visibility == 'public':
+ public_funcs.append(entry.cname)
+ if public_funcs:
+ env.use_utility_code(Nodes.c_api_import_code)
+ code.putln(
+ "static __Pyx_CApiTabEntry %s[] = {" %
+ Naming.c_api_tab_cname)
+ public_funcs.sort()
+ for entry_cname in public_funcs:
+ code.putln('{"%s", %s},' % (entry_cname, entry_cname))
+ code.putln(
+ "{0, 0}")
+ code.putln(
+ "};")
+
+ def generate_c_api_import_code(self, env, h_code):
+ # this is written to the header file!
+ h_code.put("""
+ /* Return -1 and set exception on error, 0 on success. */
+ static int
+ import_%(name)s(PyObject *module)
+ {
+ if (module != NULL)
+ {
+ int (*init)(struct {const char *s; const void **p;}*);
+ PyObject* c_api_init;
+
+ c_api_init = PyObject_GetAttrString(module,
+ "_import_c_api");
+ if (!c_api_init)
+ return -1;
+ if (!PyCObject_Check(c_api_init))
+ {
+ Py_DECREF(c_api_init);
+ PyErr_SetString(PyExc_RuntimeError,
+ "%(name)s module provided an invalid C-API reference");
+ return -1;
+ }
+
+ init = PyCObject_AsVoidPtr(c_api_init);
+ Py_DECREF(c_api_init);
+ if (!init)
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "%(name)s module returned NULL pointer for C-API init function");
+ return -1;
+ }
+
+ if (init(_%(name)s_API))
+ return -1;
+ }
+ return 0;
+ }
+ """.replace('\n ', '\n') % {'name' : env.module_name})
+
+ def generate_c_api_init_code(self, env, code):
+ public_funcs = []
+ for entry in env.cfunc_entries:
+ if entry.visibility == 'public':
+ public_funcs.append(entry)
+ if public_funcs:
+ code.putln('if (__Pyx_InitCApi(%s) < 0) %s' % (
+ Naming.module_cname,
+ code.error_goto(self.pos)))
+
def generate_filename_init_prototype(self, code):
code.putln("");
code.putln("static void %s(void); /*proto*/" % Naming.fileinit_cname)
self.generate_intern_code(env, code)
#code.putln("/*--- String init code ---*/")
self.generate_string_init_code(env, code)
+ #code.putln("/*--- External C API setup code ---*/")
+ self.generate_c_api_init_code(env, code)
#code.putln("/*--- Builtin init code ---*/")
self.generate_builtin_init_code(env, code)
#code.putln("/*--- Global init code ---*/")
dll_linkage = None
header = self.return_type.declaration_code(entity,
dll_linkage = dll_linkage)
- if self.visibility <> 'private':
+ if self.visibility == 'private':
+ storage_class = "static "
+ elif self.visibility == 'extern':
storage_class = "%s " % Naming.extern_c_macro
else:
- storage_class = "static "
+ storage_class = ""
code.putln("%s%s%s {" % (
storage_class,
self.modifiers,
#env.recycle_pending_temps() # TEMPORARY
def generate_execution_code(self, code):
+ code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
self.cond.generate_evaluation_code(code)
if self.value:
self.value.generate_evaluation_code(code)
self.cond.generate_disposal_code(code)
if self.value:
self.value.generate_disposal_code(code)
+ code.putln("#endif")
class IfStatNode(StatNode):
utility_function_predeclarations = \
"""
+typedef struct {const char *s; const void **p;} __Pyx_CApiTabEntry; /*proto*/
typedef struct {PyObject **p; char *s;} __Pyx_InternTabEntry; /*proto*/
typedef struct {PyObject **p; char *s; long n;} __Pyx_StringTabEntry; /*proto*/
"""]
#------------------------------------------------------------------------------------
+
+c_api_import_code = [
+"""
+static int __Pyx_InitCApi(PyObject *module); /*proto*/
+static int __Pyx_ImportModuleCApi(__Pyx_CApiTabEntry *t); /*proto*/
+""","""
+static int __Pyx_ImportModuleCApi(__Pyx_CApiTabEntry *t) {
+ __Pyx_CApiTabEntry *api_t;
+ while (t->s) {
+ if (*t->s == '\\0')
+ continue; /* shortcut for erased string entries */
+ api_t = %(API_TAB)s;
+ while ((api_t->s) && (strcmp(api_t->s, t->s) < 0))
+ ++api_t;
+ if ((!api_t->p) || (strcmp(api_t->s, t->s) != 0)) {
+ PyErr_Format(PyExc_ValueError,
+ "Unknown function name in C API: %%s", t->s);
+ return -1;
+ }
+ *t->p = api_t->p;
+ ++t;
+ }
+ return 0;
+}
+
+static int __Pyx_InitCApi(PyObject *module) {
+ int result;
+ PyObject* cobj = PyCObject_FromVoidPtr(&__Pyx_ImportModuleCApi, NULL);
+ if (!cobj)
+ return -1;
+
+ result = PyObject_SetAttrString(module, "_import_c_api", cobj);
+ Py_DECREF(cobj);
+ return result;
+}
+""" % {'API_TAB' : Naming.c_api_tab_cname}
+]
+#------------------------------------------------------------------------------------