summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2015-05-17 09:22:15 +0200
committerArmin Rigo <arigo@tunes.org>2015-05-17 09:22:15 +0200
commitd58366642899f3cbb5fb45ae9564fb7627a3ed13 (patch)
treee740f6f485fcc60906860e86751da26ed86235f9
parent387e34fa34ab4d80c1025d45b27f69aabf725695 (diff)
downloadcffi-d58366642899f3cbb5fb45ae9564fb7627a3ed13.tar.gz
Best-effort attempt at supporting C++. There is still one issue shown
in test_recompiler if we replace "if 0:" with "if 1:".
-rw-r--r--cffi/_cffi_include.h11
-rw-r--r--cffi/api.py18
-rw-r--r--cffi/recompiler.py19
-rw-r--r--demo/bsdopendirtype_build.py4
-rw-r--r--testing/cffi1/test_recompiler.py3
5 files changed, 35 insertions, 20 deletions
diff --git a/cffi/_cffi_include.h b/cffi/_cffi_include.h
index 84cb3a9..64efdff 100644
--- 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 @@ static void *_cffi_exports[_CFFI_NUM_EXPORTS];
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 @@ static PyObject *_cffi_init(char *module_name, Py_ssize_t version,
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 @@ static PyObject *_cffi_init(char *module_name, Py_ssize_t version,
#else
# define _CFFI_UNUSED_FN /* nothing */
#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/cffi/api.py b/cffi/api.py
index 2b7e4ad..0e24c33 100644
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -475,13 +475,14 @@ class FFI(object):
('_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 @@ class FFI(object):
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 @@ class FFI(object):
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 @@ class FFI(object):
#
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 @@ class FFI(object):
#
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 @@ class FFI(object):
#
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
index 65ce2cd..8481726 100644
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -17,7 +17,7 @@ class GlobalExpr:
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 @@ class Recompiler:
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 @@ class Recompiler:
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 @@ class Recompiler:
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 @@ def _get_extension(module_name, c_file, kwds):
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
index a771b68..abfe064 100644
--- a/demo/bsdopendirtype_build.py
+++ b/demo/bsdopendirtype_build.py
@@ -15,9 +15,11 @@ ffi.cdef("""
""")
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
index 023dd5b..6aa964c 100644
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -20,6 +20,9 @@ def verify(ffi, module_name, source, *args, **kwds):
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)