Author: Armin Rigo <[email protected]>
Branch: cffi-1.0
Changeset: r2019:eea21524de0a
Date: 2015-05-17 09:22 +0200
http://bitbucket.org/cffi/cffi/changeset/eea21524de0a/
Log: Best-effort attempt at supporting C++. There is still one issue
shown in test_recompiler if we replace "if 0:" with "if 1:".
diff --git a/cffi/_cffi_include.h b/cffi/_cffi_include.h
--- a/cffi/_cffi_include.h
+++ b/cffi/_cffi_include.h
@@ -1,4 +1,7 @@
#include <Python.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
#include <stddef.h>
#include "parse_c_type.h"
@@ -145,7 +148,7 @@
assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \
(CTypeDescrObject *)_cffi_types[index])
-static PyObject *_cffi_init(char *module_name, Py_ssize_t version,
+static PyObject *_cffi_init(const char *module_name, Py_ssize_t version,
const struct _cffi_type_context_s *ctx)
{
PyObject *module, *o_arg, *new_module;
@@ -165,7 +168,7 @@
goto failure;
new_module = PyObject_CallMethod(
- module, "_init_cffi_1_0_external_module", "O", o_arg);
+ module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg);
Py_DECREF(o_arg);
Py_DECREF(module);
@@ -200,3 +203,7 @@
#else
# define _CFFI_UNUSED_FN /* nothing */
#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -475,13 +475,14 @@
('_UNICODE', '1')]
kwds['define_macros'] = defmacros
- def set_source(self, module_name, source, **kwds):
+ def set_source(self, module_name, source, source_extension='.c', **kwds):
if hasattr(self, '_assigned_source'):
raise ValueError("set_source() cannot be called several times "
"per ffi object")
if not isinstance(module_name, basestring):
raise TypeError("'module_name' must be a string")
- self._assigned_source = (source, kwds, str(module_name))
+ self._assigned_source = (str(module_name), source,
+ source_extension, kwds)
def distutils_extension(self, tmpdir='build', verbose=True):
from distutils.dir_util import mkpath
@@ -492,7 +493,7 @@
return self.verifier.get_extension()
raise ValueError("set_source() must be called before"
" distutils_extension()")
- source, kwds, module_name = self._assigned_source
+ module_name, source, source_extension, kwds = self._assigned_source
if source is None:
raise TypeError("distutils_extension() is only for C extension "
"modules, not for dlopen()-style pure Python "
@@ -500,6 +501,7 @@
mkpath(tmpdir)
ext, updated = recompile(self, module_name,
source, tmpdir=tmpdir,
+ source_extension=source_extension,
call_c_compiler=False, **kwds)
if verbose:
if updated:
@@ -513,7 +515,7 @@
#
if not hasattr(self, '_assigned_source'):
raise ValueError("set_source() must be called before
emit_c_code()")
- source, kwds, module_name = self._assigned_source
+ module_name, source, source_extension, kwds = self._assigned_source
if source is None:
raise TypeError("emit_c_code() is only for C extension modules, "
"not for dlopen()-style pure Python modules")
@@ -525,7 +527,7 @@
#
if not hasattr(self, '_assigned_source'):
raise ValueError("set_source() must be called before
emit_c_code()")
- source, kwds, module_name = self._assigned_source
+ module_name, source, source_extension, kwds = self._assigned_source
if source is not None:
raise TypeError("emit_python_code() is only for dlopen()-style "
"pure Python modules, not for C extension modules")
@@ -537,9 +539,9 @@
#
if not hasattr(self, '_assigned_source'):
raise ValueError("set_source() must be called before compile()")
- source, kwds, module_name = self._assigned_source
- return recompile(self, module_name,
- source, tmpdir=tmpdir, **kwds)
+ module_name, source, source_extension, kwds = self._assigned_source
+ return recompile(self, module_name, source, tmpdir=tmpdir,
+ source_extension=source_extension, **kwds)
def _load_backend_lib(backend, name, flags):
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -17,7 +17,7 @@
self.check_value = check_value
def as_c_expr(self):
- return ' { "%s", %s, %s, %s },' % (
+ return ' { "%s", (void *)%s, %s, %s },' % (
self.name, self.address, self.type_op.as_c_expr(), self.size)
def as_python_expr(self):
@@ -333,8 +333,8 @@
prnt('static const char * const _cffi_includes[] = {')
for ffi_to_include in self.ffi._included_ffis:
try:
- included_source, _, included_module_name = (
- ffi_to_include._assigned_source)
+ included_module_name, included_source = (
+ ffi_to_include._assigned_source[:2])
except AttributeError:
raise ffiplatform.VerificationError(
"ffi object %r includes %r, but the latter has not "
@@ -428,8 +428,8 @@
for i in range(num_includes):
ffi_to_include = self.ffi._included_ffis[i]
try:
- included_source, _, included_module_name = (
- ffi_to_include._assigned_source)
+ included_module_name, included_source = (
+ ffi_to_include._assigned_source[:2])
except AttributeError:
raise ffiplatform.VerificationError(
"ffi object %r includes %r, but the latter has not "
@@ -516,7 +516,8 @@
self._prnt(' if (datasize != 0) {')
self._prnt(' if (datasize < 0)')
self._prnt(' %s;' % errcode)
- self._prnt(' %s = alloca((size_t)datasize);' % (tovar,))
+ self._prnt(' %s = (%s)alloca((size_t)datasize);' % (
+ tovar, tp.get_c_name('')))
self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,))
self._prnt(' if (_cffi_convert_array_from_object('
'(char *)%s, _cffi_type(%d), %s) < 0)' % (
@@ -1122,15 +1123,15 @@
source_name = ffiplatform.maybe_relative_path(c_file)
return ffiplatform.get_extension(source_name, module_name, **kwds)
-def recompile(ffi, module_name, preamble, tmpdir='.',
- call_c_compiler=True, c_file=None, **kwds):
+def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True,
+ c_file=None, source_extension='.c', **kwds):
if not isinstance(module_name, str):
module_name = module_name.encode('ascii')
if ffi._windows_unicode:
ffi._apply_windows_unicode(kwds)
if preamble is not None:
if c_file is None:
- c_file = os.path.join(tmpdir, module_name + '.c')
+ c_file = os.path.join(tmpdir, module_name + source_extension)
ext = _get_extension(module_name, c_file, kwds)
updated = make_c_source(ffi, module_name, preamble, c_file)
if call_c_compiler:
diff --git a/demo/bsdopendirtype_build.py b/demo/bsdopendirtype_build.py
--- a/demo/bsdopendirtype_build.py
+++ b/demo/bsdopendirtype_build.py
@@ -15,9 +15,11 @@
""")
ffi.set_source("_bsdopendirtype", """
+extern "C" {
#include <sys/types.h>
#include <dirent.h>
-""")
+}
+""", source_extension='.cpp')
if __name__ == '__main__':
ffi.compile()
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -20,6 +20,9 @@
kwds.setdefault('undef_macros', ['NDEBUG'])
module_name = '_CFFI_' + module_name
ffi.set_source(module_name, source)
+ if 0: # test the .cpp mode too
+ kwds.setdefault('source_extension', '.cpp')
+ source = 'extern "C" {\n%s\n}' % (source,)
return recompiler._verify(ffi, module_name, source, *args, **kwds)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit