summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscoder <stefan_ml@behnel.de>2023-04-13 11:32:37 +0200
committerGitHub <noreply@github.com>2023-04-13 11:32:37 +0200
commit2ea40bbccf2b0e85b88c0bbaa107edc38d0fd690 (patch)
treeebf11b79040c17de1c1a10a30fa9ca7308fc1173
parent09484713cead73353ef3354e96677e0c7b6e293f (diff)
downloadcython-2ea40bbccf2b0e85b88c0bbaa107edc38d0fd690.tar.gz
Add a "CYTHON_EXTERN_C" macro to allow redefining "__PYX_EXTERN_C" on user side (GH-5371)
See https://github.com/cython/cython/pull/5366 Add a warning for users who already defined "__PYX_EXTERN_C" before that there is a new macro for this. Also try to reverse-engineer expressive names for the different test cases.
-rw-r--r--Cython/Compiler/ModuleNode.py12
-rw-r--r--tests/run/cpp_extern.srctree87
2 files changed, 56 insertions, 43 deletions
diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py
index 225eced26..fa5628397 100644
--- a/Cython/Compiler/ModuleNode.py
+++ b/Cython/Compiler/ModuleNode.py
@@ -891,7 +891,17 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_extern_c_macro_definition(self, code, is_cpp):
name = Naming.extern_c_macro
- code.putln("#ifndef %s" % name)
+ code.putln("#ifdef CYTHON_EXTERN_C")
+ # make sure that user overrides always take precedence
+ code.putln(' #undef %s' % name)
+ code.putln(' #define %s CYTHON_EXTERN_C' % name)
+ code.putln("#elif defined(%s)" % name)
+ code.putln(" #ifdef _MSC_VER")
+ code.putln(" #pragma message (\"Please do not define the '%s' macro externally. Use 'CYTHON_EXTERN_C' instead.\")" % name)
+ code.putln(" #else")
+ code.putln(" #warning Please do not define the '%s' macro externally. Use 'CYTHON_EXTERN_C' instead." % name)
+ code.putln(" #endif")
+ code.putln("#else")
if is_cpp:
code.putln(' #define %s extern "C++"' % name)
else:
diff --git a/tests/run/cpp_extern.srctree b/tests/run/cpp_extern.srctree
index 86f069455..85374b2d0 100644
--- a/tests/run/cpp_extern.srctree
+++ b/tests/run/cpp_extern.srctree
@@ -4,9 +4,9 @@
"""
PYTHON setup.py build_ext --inplace
-PYTHON -c "from foo import test; test()"
-PYTHON -c "from bar import test; test()"
-PYTHON -c "from baz import test; test()"
+PYTHON -c "from include_as_c_and_cpp import test; test()"
+PYTHON -c "from include_from_c_and_cpp import test; test()"
+PYTHON -c "from cdefines import test; test()"
"""
######## setup.py ########
@@ -16,32 +16,33 @@ from Cython.Distutils.extension import Extension
from distutils.core import setup
import sys
-foo = Extension(
- "foo",
- ["foo.pyx", "foo1.cpp", "foo2.cpp"],
+include_as_c_and_cpp = Extension(
+ "include_as_c_and_cpp",
+ ["include_as_c_and_cpp.pyx", "include_as_c.cpp", "include_as_cpp.cpp"],
)
-bar = Extension(
- "bar",
- ["bar.pyx", "bar1.c", "bar2.cpp"],
+include_from_c_and_cpp = Extension(
+ "include_from_c_and_cpp",
+ ["include_from_c_and_cpp.pyx", "include_from_c.c", "include_from_cpp.cpp"],
)
-baz = Extension(
- "baz",
- ["baz.pyx", "baz1.c", "baz2.cpp"],
- define_macros = [("__PYX_EXTERN_C", 'extern "C"')],
+cdefines = Extension(
+ "cdefines",
+ ["cdefines.pyx", "cdefines_clean.c", "cdefines_plain.cpp"],
+ define_macros = [("CYTHON_EXTERN_C", 'extern "C"')],
)
-ext_modules = [foo, bar]
+ext_modules = [include_as_c_and_cpp, include_from_c_and_cpp]
if sys.platform != "win32":
# It's very hard to get the command-line macro define to escape properly on Windows,
# so skip it
- ext_modules.append(baz)
+ ext_modules.append(cdefines)
setup(
ext_modules=cythonize(ext_modules),
)
-######## foo.pyx ########
+
+######## include_as_c_and_cpp.pyx ########
# distutils: language = c++
@@ -50,7 +51,7 @@ from libcpp cimport vector
cdef public vector.vector[int] get_vector():
return [1,2,3]
-cdef extern from "foo_header.h":
+cdef extern from "include_as_c_and_cpp_header.h":
cdef size_t size_vector1()
cdef size_t size_vector2()
@@ -58,40 +59,41 @@ def test():
assert size_vector1() == 3
assert size_vector2() == 3
-######## foo_header.h ########
+######## include_as_c_and_cpp_header.h ########
size_t size_vector1();
size_t size_vector2();
-######## foo1.cpp ########
+######## include_as_cpp.cpp ########
#include <vector>
-#include "foo.h"
+#include "include_as_c_and_cpp.h"
size_t size_vector1() {
return get_vector().size();
}
-######## foo2.cpp ########
+######## include_as_c.cpp ########
#include <vector>
extern "C" {
// #include within `extern "C"` is legal.
// We want to make sure here that Cython C++ functions are flagged as `extern "C++"`.
// Otherwise they would be interpreted with C-linkage if the header is include within a `extern "C"` block.
-#include "foo.h"
+#include "include_as_c_and_cpp.h"
}
size_t size_vector2() {
return get_vector().size();
}
-######## bar.pyx ########
+
+######## include_from_c_and_cpp.pyx ########
cdef public char get_char():
return 42
-cdef extern from "bar_header.h":
+cdef extern from "include_from_c_and_cpp_header.h":
cdef int get_int1()
cdef int get_int2()
@@ -99,33 +101,34 @@ def test():
assert get_int1() == 42
assert get_int2() == 42
-######## bar_header.h ########
+######## include_from_c_and_cpp_header.h ########
int get_int1();
int get_int2();
-######## bar1.c ########
+######## include_from_c.c ########
-#include "bar.h"
+#include "include_from_c_and_cpp.h"
int get_int1() { return (int)get_char(); }
-######## bar2.cpp ########
+######## include_from_cpp.cpp ########
extern "C" {
-#include "bar.h"
+#include "include_from_c_and_cpp.h"
}
extern "C" int get_int2() { return (int)get_char(); }
-######## baz.pyx ########
+
+######## cdefines.pyx ########
# distutils: language = c++
cdef public char get_char():
return 42
-cdef extern from "baz_header.h":
+cdef extern from "cdefines_header.h":
cdef int get_int1()
cdef int get_int2()
@@ -133,32 +136,32 @@ def test():
assert get_int1() == 42
assert get_int2() == 42
-######## baz_header.h ########
+######## cdefines_header.h ########
#ifdef __cplusplus
- #define BAZ_EXTERN_C extern "C"
+ #define cdefines_EXTERN_C extern "C"
#else
- #define BAZ_EXTERN_C
+ #define cdefines_EXTERN_C
#endif
-BAZ_EXTERN_C int get_int1();
+cdefines_EXTERN_C int get_int1();
int get_int2();
-######## baz1.c ########
+######## cdefines_clean.c ########
-#undef __PYX_EXTERN_C
-#define __PYX_EXTERN_C
-#include "baz.h"
+#undef CYTHON_EXTERN_C
+#define CYTHON_EXTERN_C
+#include "cdefines.h"
int get_int1() { return (int)get_char(); }
-######## baz2.cpp ########
+######## cdefines_plain.cpp ########
-#include "baz.h"
+#include "cdefines.h"
int get_int2() { return (int)get_char(); }
-######## baz.py ##########
+######## cdefines.py ##########
# Dummy module so Windows test works
import sys