Author: Armin Rigo <ar...@tunes.org>
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
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to