[pypy-commit] pypy seperate-strucmember_h: Move structmember.h out of Python.h.
devin.jeanpierre
pypy.commits at gmail.com
Tue Feb 9 16:33:30 EST 2016
Author: Devin Jeanpierre <jeanpierreda at gmail.com>
Branch: seperate-strucmember_h
Changeset: r82133:84085c039403
Date: 2016-01-31 01:49 -0800
http://bitbucket.org/pypy/pypy/changeset/84085c039403/
Log: Move structmember.h out of Python.h.
Rough breakdown of changes:
* Where Python.h is included by .c files, also include structmember.h
* Add pypy_structmember_decl.h file which is included by
structmember.h
* Allow cpython_api functions to change which headers they are added
to.
The first two are very manual and icky, and I don't like how I did
them. It feels like a hack. But I'm not sure of a better way to do
it without more substantive rewrites.
The last part was an API changes to cpython_api, so very invasive,
but clean. Maybe the implementation is dumb.
One last note: The header file being added in copy_header_files()
doesn't seem to matter. I left it in anyway "just in case". Does it
matter?
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -59,7 +59,7 @@
class CConfig:
_compilation_info_ = ExternalCompilationInfo(
include_dirs=include_dirs,
- includes=['Python.h', 'stdarg.h'],
+ includes=['Python.h', 'stdarg.h', 'structmember.h'],
compile_extra=['-DPy_BUILD_CORE'],
)
@@ -129,6 +129,7 @@
for name in constant_names:
setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name))
udir.join('pypy_decl.h').write("/* Will be filled later */\n")
+udir.join('pypy_structmember_decl.h').write("/* Will be filled later */\n")
udir.join('pypy_macros.h').write("/* Will be filled later */\n")
globals().update(rffi_platform.configure(CConfig_constants))
@@ -147,7 +148,7 @@
# XXX: 20 lines of code to recursively copy a directory, really??
assert dstdir.check(dir=True)
headers = include_dir.listdir('*.h') + include_dir.listdir('*.inl')
- for name in ("pypy_decl.h", "pypy_macros.h"):
+ for name in ("pypy_decl.h", "pypy_macros.h", "pypy_structmember_decl.h"):
headers.append(udir.join(name))
_copy_header_files(headers, dstdir)
@@ -232,7 +233,7 @@
wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
return wrapper
-def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, external=True,
+def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, header='pypy_decl.h',
gil=None):
"""
Declares a function to be exported.
@@ -241,8 +242,8 @@
special value 'CANNOT_FAIL' (also when restype is Void) turns an eventual
exception into a wrapped SystemError. Unwrapped exceptions also cause a
SytemError.
- - set `external` to False to get a C function pointer, but not exported by
- the API headers.
+ - `header` is the header file to export the function in, Set to None to get
+ a C function pointer, but not exported by the API headers.
- set `gil` to "acquire", "release" or "around" to acquire the GIL,
release the GIL, or both
"""
@@ -263,7 +264,7 @@
def decorate(func):
func_name = func.func_name
- if external:
+ if header is not None:
c_name = None
else:
c_name = func_name
@@ -271,7 +272,7 @@
c_name=c_name, gil=gil)
func.api_func = api_function
- if external:
+ if header is not None:
assert func_name not in FUNCTIONS, (
"%s already registered" % func_name)
@@ -363,8 +364,9 @@
unwrapper_catch = make_unwrapper(True)
unwrapper_raise = make_unwrapper(False)
- if external:
+ if header is not None:
FUNCTIONS[func_name] = api_function
+ FUNCTIONS_BY_HEADER.setdefault(header, {})[func_name] = api_function
INTERPLEVEL_API[func_name] = unwrapper_catch # used in tests
return unwrapper_raise # used in 'normal' RPython code.
return decorate
@@ -383,6 +385,7 @@
INTERPLEVEL_API = {}
FUNCTIONS = {}
+FUNCTIONS_BY_HEADER = {}
# These are C symbols which cpyext will export, but which are defined in .c
# files somewhere in the implementation of cpyext (rather than being defined in
@@ -811,6 +814,7 @@
global_code = '\n'.join(global_objects)
prologue = ("#include <Python.h>\n"
+ "#include <structmember.h>\n"
"#include <src/thread.c>\n")
code = (prologue +
struct_declaration_code +
@@ -956,34 +960,62 @@
pypy_macros_h = udir.join('pypy_macros.h')
pypy_macros_h.write('\n'.join(pypy_macros))
+def _header_to_guard(header_name):
+ return '_PYPY_' + header_name.replace('.', '_').upper()
+
+def _decl_header_top(header_name):
+ guard = _header_to_guard(header_name)
+ header = [
+ "#ifndef %s\n" % guard,
+ "#define %s\n" % guard,
+ "#ifndef PYPY_STANDALONE\n",
+ "#ifdef __cplusplus",
+ "extern \"C\" {",
+ "#endif\n",
+ '#define Signed long /* xxx temporary fix */\n',
+ '#define Unsigned unsigned long /* xxx temporary fix */\n'
+ ]
+ if header_name == 'pypy_decl.h': # XXX don't send for code review unless I'm sure this is necessary
+ for decl in FORWARD_DECLS:
+ header.append("%s;" % (decl,))
+ return header
+
+def _decl_header_bottom(header_name):
+ return [
+ '#undef Signed /* xxx temporary fix */\n',
+ '#undef Unsigned /* xxx temporary fix */\n',
+ "#ifdef __cplusplus",
+ "}",
+ "#endif",
+ "#endif /*PYPY_STANDALONE*/\n",
+ "#endif /*%s*/\n" % _header_to_guard(header_name),
+ ]
+
def generate_decls_and_callbacks(db, export_symbols, api_struct=True):
"NOT_RPYTHON"
# implement function callbacks and generate function decls
functions = []
- pypy_decls = []
- pypy_decls.append("#ifndef _PYPY_PYPY_DECL_H\n")
- pypy_decls.append("#define _PYPY_PYPY_DECL_H\n")
- pypy_decls.append("#ifndef PYPY_STANDALONE\n")
- pypy_decls.append("#ifdef __cplusplus")
- pypy_decls.append("extern \"C\" {")
- pypy_decls.append("#endif\n")
- pypy_decls.append('#define Signed long /* xxx temporary fix */\n')
- pypy_decls.append('#define Unsigned unsigned long /* xxx temporary fix */\n')
+ decls = {}
- for decl in FORWARD_DECLS:
- pypy_decls.append("%s;" % (decl,))
+ for header_name, header_functions in FUNCTIONS_BY_HEADER.iteritems():
+ if header_name not in decls:
+ decls[header_name] = header = []
+ header.extend(_decl_header_top(header_name))
+ else:
+ header = decls[header_name]
- for name, func in sorted(FUNCTIONS.iteritems()):
- restype, args = c_function_signature(db, func)
- pypy_decls.append("PyAPI_FUNC(%s) %s(%s);" % (restype, name, args))
- if api_struct:
- callargs = ', '.join('arg%d' % (i,)
- for i in range(len(func.argtypes)))
- if func.restype is lltype.Void:
- body = "{ _pypyAPI.%s(%s); }" % (name, callargs)
- else:
- body = "{ return _pypyAPI.%s(%s); }" % (name, callargs)
- functions.append('%s %s(%s)\n%s' % (restype, name, args, body))
+ for name, func in sorted(header_functions.iteritems()):
+ restype, args = c_function_signature(db, func)
+ header.append("PyAPI_FUNC(%s) %s(%s);" % (restype, name, args))
+ if api_struct:
+ callargs = ', '.join('arg%d' % (i,)
+ for i in range(len(func.argtypes)))
+ if func.restype is lltype.Void:
+ body = "{ _pypyAPI.%s(%s); }" % (name, callargs)
+ else:
+ body = "{ return _pypyAPI.%s(%s); }" % (name, callargs)
+ functions.append('%s %s(%s)\n%s' % (restype, name, args, body))
+ pypy_decls = decls['pypy_decl.h']
for name in VA_TP_LIST:
name_no_star = process_va_name(name)
header = ('%s pypy_va_get_%s(va_list* vp)' %
@@ -999,16 +1031,11 @@
typ = 'PyObject*'
pypy_decls.append('PyAPI_DATA(%s) %s;' % (typ, name))
- pypy_decls.append('#undef Signed /* xxx temporary fix */\n')
- pypy_decls.append('#undef Unsigned /* xxx temporary fix */\n')
- pypy_decls.append("#ifdef __cplusplus")
- pypy_decls.append("}")
- pypy_decls.append("#endif")
- pypy_decls.append("#endif /*PYPY_STANDALONE*/\n")
- pypy_decls.append("#endif /*_PYPY_PYPY_DECL_H*/\n")
+ for header_name, header_decls in decls.iteritems():
+ header_decls.extend(_decl_header_bottom(header_name))
- pypy_decl_h = udir.join('pypy_decl.h')
- pypy_decl_h.write('\n'.join(pypy_decls))
+ decl_h = udir.join(header_name)
+ decl_h.write('\n'.join(header_decls))
return functions
separate_module_files = [source_dir / "varargwrapper.c",
diff --git a/pypy/module/cpyext/bufferobject.py b/pypy/module/cpyext/bufferobject.py
--- a/pypy/module/cpyext/bufferobject.py
+++ b/pypy/module/cpyext/bufferobject.py
@@ -73,7 +73,7 @@
"Don't know how to realize a buffer"))
- at cpython_api([PyObject], lltype.Void, external=False)
+ at cpython_api([PyObject], lltype.Void, header=None)
def buffer_dealloc(space, py_obj):
py_buf = rffi.cast(PyBufferObject, py_obj)
if py_buf.c_b_base:
diff --git a/pypy/module/cpyext/frameobject.py b/pypy/module/cpyext/frameobject.py
--- a/pypy/module/cpyext/frameobject.py
+++ b/pypy/module/cpyext/frameobject.py
@@ -39,7 +39,7 @@
py_frame.c_f_locals = make_ref(space, frame.get_w_locals())
rffi.setintfield(py_frame, 'c_f_lineno', frame.getorcreatedebug().f_lineno)
- at cpython_api([PyObject], lltype.Void, external=False)
+ at cpython_api([PyObject], lltype.Void, header=None)
def frame_dealloc(space, py_obj):
py_frame = rffi.cast(PyFrameObject, py_obj)
py_code = rffi.cast(PyObject, py_frame.c_f_code)
diff --git a/pypy/module/cpyext/funcobject.py b/pypy/module/cpyext/funcobject.py
--- a/pypy/module/cpyext/funcobject.py
+++ b/pypy/module/cpyext/funcobject.py
@@ -56,7 +56,7 @@
assert isinstance(w_obj, Function)
py_func.c_func_name = make_ref(space, space.wrap(w_obj.name))
- at cpython_api([PyObject], lltype.Void, external=False)
+ at cpython_api([PyObject], lltype.Void, header=None)
def function_dealloc(space, py_obj):
py_func = rffi.cast(PyFunctionObject, py_obj)
Py_DecRef(space, py_func.c_func_name)
@@ -75,7 +75,7 @@
rffi.setintfield(py_code, 'c_co_flags', co_flags)
rffi.setintfield(py_code, 'c_co_argcount', w_obj.co_argcount)
- at cpython_api([PyObject], lltype.Void, external=False)
+ at cpython_api([PyObject], lltype.Void, header=None)
def code_dealloc(space, py_obj):
py_code = rffi.cast(PyCodeObject, py_obj)
Py_DecRef(space, py_code.c_co_name)
diff --git a/pypy/module/cpyext/include/Python.h b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -132,9 +132,6 @@
/* Missing definitions */
#include "missing.h"
-// XXX This shouldn't be included here
-#include "structmember.h"
-
#include <pypy_decl.h>
/* Define macros for inline documentation. */
diff --git a/pypy/module/cpyext/include/structmember.h b/pypy/module/cpyext/include/structmember.h
--- a/pypy/module/cpyext/include/structmember.h
+++ b/pypy/module/cpyext/include/structmember.h
@@ -55,3 +55,6 @@
}
#endif
#endif /* !Py_STRUCTMEMBER_H */
+
+/* API functions. */
+#include "pypy_structmember_decl.h"
diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -50,7 +50,7 @@
py_func.c_m_self = make_ref(space, w_obj.w_self)
py_func.c_m_module = make_ref(space, w_obj.w_module)
- at cpython_api([PyObject], lltype.Void, external=False)
+ at cpython_api([PyObject], lltype.Void, header=None)
def cfunction_dealloc(space, py_obj):
py_func = rffi.cast(PyCFunctionObject, py_obj)
Py_DecRef(space, py_func.c_m_self)
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -70,7 +70,7 @@
alloc : allocate and basic initialization of a raw PyObject
attach : Function called to tie a raw structure to a pypy object
realize : Function called to create a pypy object from a raw struct
- dealloc : a cpython_api(external=False), similar to PyObject_dealloc
+ dealloc : a cpython_api(header=None), similar to PyObject_dealloc
"""
tp_basestruct = kw.pop('basestruct', PyObject.TO)
diff --git a/pypy/module/cpyext/pytraceback.py b/pypy/module/cpyext/pytraceback.py
--- a/pypy/module/cpyext/pytraceback.py
+++ b/pypy/module/cpyext/pytraceback.py
@@ -41,7 +41,7 @@
rffi.setintfield(py_traceback, 'c_tb_lasti', traceback.lasti)
rffi.setintfield(py_traceback, 'c_tb_lineno',traceback.get_lineno())
- at cpython_api([PyObject], lltype.Void, external=False)
+ at cpython_api([PyObject], lltype.Void, header=None)
def traceback_dealloc(space, py_obj):
py_traceback = rffi.cast(PyTracebackObject, py_obj)
Py_DecRef(space, rffi.cast(PyObject, py_traceback.c_tb_next))
diff --git a/pypy/module/cpyext/sliceobject.py b/pypy/module/cpyext/sliceobject.py
--- a/pypy/module/cpyext/sliceobject.py
+++ b/pypy/module/cpyext/sliceobject.py
@@ -36,7 +36,7 @@
py_slice.c_stop = make_ref(space, w_obj.w_stop)
py_slice.c_step = make_ref(space, w_obj.w_step)
- at cpython_api([PyObject], lltype.Void, external=False)
+ at cpython_api([PyObject], lltype.Void, header=None)
def slice_dealloc(space, py_obj):
"""Frees allocated PyStringObject resources.
"""
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -309,7 +309,7 @@
return space.wrap(generic_cpy_call(space, func_target, w_self, w_other))
- at cpython_api([PyTypeObjectPtr, PyObject, PyObject], PyObject, external=False)
+ at cpython_api([PyTypeObjectPtr, PyObject, PyObject], PyObject, header=None)
def slot_tp_new(space, type, w_args, w_kwds):
from pypy.module.cpyext.tupleobject import PyTuple_Check
pyo = rffi.cast(PyObject, type)
@@ -320,30 +320,30 @@
w_args_new = space.newtuple(args_w)
return space.call(w_func, w_args_new, w_kwds)
- at cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, error=-1, external=False)
+ at cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, error=-1, header=None)
def slot_tp_init(space, w_self, w_args, w_kwds):
w_descr = space.lookup(w_self, '__init__')
args = Arguments.frompacked(space, w_args, w_kwds)
space.get_and_call_args(w_descr, w_self, args)
return 0
- at cpython_api([PyObject, PyObject, PyObject], PyObject, external=False)
+ at cpython_api([PyObject, PyObject, PyObject], PyObject, header=None)
def slot_tp_call(space, w_self, w_args, w_kwds):
return space.call(w_self, w_args, w_kwds)
- at cpython_api([PyObject], PyObject, external=False)
+ at cpython_api([PyObject], PyObject, header=None)
def slot_tp_str(space, w_self):
return space.str(w_self)
- at cpython_api([PyObject], PyObject, external=False)
+ at cpython_api([PyObject], PyObject, header=None)
def slot_nb_int(space, w_self):
return space.int(w_self)
- at cpython_api([PyObject], PyObject, external=False)
+ at cpython_api([PyObject], PyObject, header=None)
def slot_tp_iter(space, w_self):
return space.iter(w_self)
- at cpython_api([PyObject], PyObject, external=False)
+ at cpython_api([PyObject], PyObject, header=None)
def slot_tp_iternext(space, w_self):
return space.next(w_self)
@@ -371,7 +371,7 @@
return
@cpython_api([PyObject, PyObject, PyObject], rffi.INT_real,
- error=-1, external=True) # XXX should not be exported
+ error=-1) # XXX should be header=None
@func_renamer("cpyext_tp_setattro_%s" % (typedef.name,))
def slot_tp_setattro(space, w_self, w_name, w_value):
if w_value is not None:
@@ -385,8 +385,7 @@
if getattr_fn is None:
return
- @cpython_api([PyObject, PyObject], PyObject,
- external=True)
+ @cpython_api([PyObject, PyObject], PyObject)
@func_renamer("cpyext_tp_getattro_%s" % (typedef.name,))
def slot_tp_getattro(space, w_self, w_name):
return space.call_function(getattr_fn, w_self, w_name)
diff --git a/pypy/module/cpyext/stringobject.py b/pypy/module/cpyext/stringobject.py
--- a/pypy/module/cpyext/stringobject.py
+++ b/pypy/module/cpyext/stringobject.py
@@ -103,7 +103,7 @@
track_reference(space, py_obj, w_obj)
return w_obj
- at cpython_api([PyObject], lltype.Void, external=False)
+ at cpython_api([PyObject], lltype.Void, header=None)
def string_dealloc(space, py_obj):
"""Frees allocated PyStringObject resources.
"""
diff --git a/pypy/module/cpyext/structmember.py b/pypy/module/cpyext/structmember.py
--- a/pypy/module/cpyext/structmember.py
+++ b/pypy/module/cpyext/structmember.py
@@ -31,8 +31,10 @@
(T_PYSSIZET, rffi.SSIZE_T, PyLong_AsSsize_t),
])
+_HEADER = 'pypy_structmember_decl.h'
- at cpython_api([PyObject, lltype.Ptr(PyMemberDef)], PyObject)
+
+ at cpython_api([PyObject, lltype.Ptr(PyMemberDef)], PyObject, header=_HEADER)
def PyMember_GetOne(space, obj, w_member):
addr = rffi.cast(ADDR, obj)
addr += w_member.c_offset
@@ -83,7 +85,8 @@
return w_result
- at cpython_api([PyObject, lltype.Ptr(PyMemberDef), PyObject], rffi.INT_real, error=-1)
+ at cpython_api([PyObject, lltype.Ptr(PyMemberDef), PyObject], rffi.INT_real,
+ error=-1, header=_HEADER)
def PyMember_SetOne(space, obj, w_member, w_value):
addr = rffi.cast(ADDR, obj)
addr += w_member.c_offset
diff --git a/pypy/module/cpyext/test/test_translate.py b/pypy/module/cpyext/test/test_translate.py
--- a/pypy/module/cpyext/test/test_translate.py
+++ b/pypy/module/cpyext/test/test_translate.py
@@ -19,7 +19,7 @@
@specialize.memo()
def get_tp_function(space, typedef):
- @cpython_api([], lltype.Signed, error=-1, external=False)
+ @cpython_api([], lltype.Signed, error=-1, header=None)
def slot_tp_function(space):
return typedef.value
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -183,7 +183,7 @@
if pto.c_tp_new:
add_tp_new_wrapper(space, dict_w, pto)
- at cpython_api([PyObject, PyObject, PyObject], PyObject, external=False)
+ at cpython_api([PyObject, PyObject, PyObject], PyObject, header=None)
def tp_new_wrapper(space, self, w_args, w_kwds):
tp_new = rffi.cast(PyTypeObjectPtr, self).c_tp_new
@@ -311,7 +311,7 @@
dealloc=type_dealloc)
- at cpython_api([PyObject], lltype.Void, external=False)
+ at cpython_api([PyObject], lltype.Void, header=None)
def subtype_dealloc(space, obj):
pto = obj.c_ob_type
base = pto
@@ -327,7 +327,7 @@
# hopefully this does not clash with the memory model assumed in
# extension modules
- at cpython_api([PyObject, Py_ssize_tP], lltype.Signed, external=False,
+ at cpython_api([PyObject, Py_ssize_tP], lltype.Signed, header=None,
error=CANNOT_FAIL)
def str_segcount(space, w_obj, ref):
if ref:
@@ -335,7 +335,7 @@
return 1
@cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
- external=False, error=-1)
+ header=None, error=-1)
def str_getreadbuffer(space, w_str, segment, ref):
from pypy.module.cpyext.stringobject import PyString_AsString
if segment != 0:
@@ -348,7 +348,7 @@
return space.len_w(w_str)
@cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
- external=False, error=-1)
+ header=None, error=-1)
def str_getcharbuffer(space, w_str, segment, ref):
from pypy.module.cpyext.stringobject import PyString_AsString
if segment != 0:
@@ -361,7 +361,7 @@
return space.len_w(w_str)
@cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
- external=False, error=-1)
+ header=None, error=-1)
def buf_getreadbuffer(space, pyref, segment, ref):
from pypy.module.cpyext.bufferobject import PyBufferObject
if segment != 0:
@@ -393,7 +393,7 @@
buf_getreadbuffer.api_func.get_wrapper(space))
pto.c_tp_as_buffer = c_buf
- at cpython_api([PyObject], lltype.Void, external=False)
+ at cpython_api([PyObject], lltype.Void, header=None)
def type_dealloc(space, obj):
from pypy.module.cpyext.object import PyObject_dealloc
obj_pto = rffi.cast(PyTypeObjectPtr, obj)
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -75,7 +75,7 @@
track_reference(space, py_obj, w_obj)
return w_obj
- at cpython_api([PyObject], lltype.Void, external=False)
+ at cpython_api([PyObject], lltype.Void, header=None)
def unicode_dealloc(space, py_obj):
py_unicode = rffi.cast(PyUnicodeObject, py_obj)
if py_unicode.c_buffer:
More information about the pypy-commit
mailing list