bt2: generate native extension as C++
authorSimon Marchi <simon.marchi@efficios.com>
Tue, 5 Nov 2024 17:17:52 +0000 (12:17 -0500)
committerSimon Marchi <simon.marchi@efficios.com>
Tue, 5 Nov 2024 19:58:27 +0000 (14:58 -0500)
Make SWIG generate the native code in C++ rather than C.  The
differences in the generated file (`native_bt.cpp`, previously
`native_bt.c`) are not significant (use of C++-style casts instead of
C-style casts, use of new/delete instead malloc/free, etc), but it will
allow us to use C++ in the typemap code.  It will help to integrate
better with other utils that are or will be written in C++.

Unfortunately, this requires more distutils hackery.  It looks like
distutils (both the copies distributed with CPython < 3.12 and the copy
in setuptools < 72.2.0) doesn't have good support for building objects
from C++ files that will end up in shared objects.  The `compiler_so`
executable gets used, defined here [1] as using the C compiler.  If
using a recent enough compiler that defaults to C++11, it works (when
calling `gcc` or `clang`, rather than `g++` or `clang++` they understand
that you want to compile C++ based on the file suffix).  But on an older
system (e.g. SLES12) with gcc 4.8, we get errors like:

    In file included from bt2/native_bt.cpp:3296:0:
    /babeltrace/src/bindings/python/bt2/bt2/native_bt_autodisc.i.h: In function 'bt_value* bt_bt2_auto_discover_source_components(const bt_value*, const bt_plugin_set*)':
    /babeltrace/src/bindings/python/bt2/bt2/native_bt_autodisc.i.h:118:9: warning: 'auto' changes meaning in C++11; please remove it [-Wc++0x-compat]
       const auto autodisc_result = static_cast<auto_source_discovery_result*>(
             ^

Things appear to have improved in setuptools 72.2.0 [2], where there's
now a `compiler_so_cxx` executable that uses the C++ compiler.  This
release doesn't appear widely available in Linux distros right now (for
instance Arch is still at 69.5.1), and we need to support distutils all
the way back to Python 3.4 anyway.

The new distutils hackery is inspired by this blog post [3].  The idea
is to override the `build_extensions()` method of
`distutils.command.build_ext.build_ext` method to set the executables on
the `distutils.ccompiler.CCompiler` instance.  Because this way of doing
things overrides the flags previously determined by distutils, we can
handle here the other hacks:

 - the hack to force our CFLAGS over sysconfig's CFLAGS (which now
   becomes CXXFLAGS because C++)
 - the hack to manually convert the include paths form on MinGW

I add to the `compiler_so_cxx` command the result of
`sysconfig.get_config_var("CCSHARED")`, which is analogous to what is
done in [2].  On Linux, for instance, this contains `-fPIC`, which is
necessary to produce objects files intended to be used in shared
objects.

[1] https://github.com/pypa/setuptools/blob/v72.1.0/setuptools/_distutils/sysconfig.py#L355-L357
[2] https://github.com/pypa/setuptools/blob/v72.2.0/setuptools/_distutils/sysconfig.py#L360-L363
[3] https://shwina.github.io/custom-compiler-linker-extensions/

Change-Id: I5999292d3a14948ef5f675a924e2360bc4d73f13
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/13431

19 files changed:
src/autodisc/autodisc.h
src/bindings/python/bt2/Makefile.am
src/bindings/python/bt2/bt2/logging.c [deleted file]
src/bindings/python/bt2/bt2/logging.cpp [new file with mode: 0644]
src/bindings/python/bt2/bt2/logging.h [deleted file]
src/bindings/python/bt2/bt2/logging.hpp [new file with mode: 0644]
src/bindings/python/bt2/bt2/native_bt.i
src/bindings/python/bt2/bt2/native_bt_autodisc.i.h
src/bindings/python/bt2/bt2/native_bt_component_class.i.h
src/bindings/python/bt2/bt2/native_bt_event_class.i
src/bindings/python/bt2/bt2/native_bt_graph.i.h
src/bindings/python/bt2/bt2/native_bt_message_iterator.i.h
src/bindings/python/bt2/bt2/native_bt_port.i
src/bindings/python/bt2/bt2/native_bt_trace.i.h
src/bindings/python/bt2/bt2/native_bt_trace_class.i.h
src/bindings/python/bt2/bt2/native_bt_value.i.h
src/bindings/python/bt2/setup.py.in
src/py-common/py-common.h
src/string-format/format-error.h

index 6a51111cd156653faadbebd6c9c24ec29a96ca99..f090682f83d0df7532566aa22482ef4962363ec1 100644 (file)
 #include <babeltrace2/func-status.h>
 #undef __BT_IN_BABELTRACE_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct auto_source_discovery {
        /* Array of `struct auto_source_discovery_result *`. */
        GPtrArray *results;
@@ -71,4 +75,8 @@ auto_source_discovery_status auto_discover_source_components(
                struct auto_source_discovery *auto_disc,
                const bt_interrupter *interrupter);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* BABELTRACE_AUTODISC_AUTODISC_H */
index 718486fcecd3058018440da996669924b45c3b9c..4819d421cee7844b6f13a95478c5e3e9db2f7109 100644 (file)
@@ -56,8 +56,8 @@ SWIG_INTERFACE_FILES =                                        \
 
 # Non-generated files built into the native library.
 STATIC_NATIVE_LIB_SRCS =                               \
-       bt2/logging.c                                   \
-       bt2/logging.h
+       bt2/logging.cpp                                 \
+       bt2/logging.hpp
 
 STATIC_BINDINGS_DEPS =                                 \
        bt2/__init__.py                                 \
@@ -105,7 +105,7 @@ STATIC_LIBRARIES_DEPS = \
        $(top_builddir)/src/string-format/libstring-format.la
 
 GENERATED_BINDINGS_DEPS =      \
-       bt2/native_bt.c         \
+       bt2/native_bt.cpp       \
        bt2/version.py          \
        setup.py
 
@@ -114,34 +114,28 @@ GENERATED_BINDINGS_DEPS = \
 # have renamed this global to `Swig_This_global`.
 #
 # Disable -Wshadow for that file.
-WARN_CFLAGS = -Wno-shadow
+WARN_CXXFLAGS = -Wno-shadow
 
-WARN_CFLAGS += -Wno-null-dereference
+WARN_CXXFLAGS += -Wno-null-dereference
 
 # Python 3.8 with SWIG 4.0.2 generates a deprecated warning for 'tp_print'
 # and in general there is not much we can do about deprecations in generated
 # code.
-WARN_CFLAGS += -Wno-deprecated-declarations
+WARN_CXXFLAGS += -Wno-deprecated-declarations
 
 # Python 3.11 + gcc 12.2.0 gave warnings of this kind in Python.h.
-WARN_CFLAGS += -Wno-redundant-decls
+WARN_CXXFLAGS += -Wno-redundant-decls
 
 # For SWIG generated code
-WARN_CFLAGS += -Wno-missing-field-initializers
-WARN_CFLAGS += -Wno-unused-parameter
+WARN_CXXFLAGS += -Wno-missing-field-initializers
+WARN_CXXFLAGS += -Wno-unused-parameter
 
-# SWIG 4.2.0 generates:
-#
-#   #if __cplusplus >=201103L
-#
-# ... leading to some `-Wundef` warnings when building the extension as C, where
-# `__cplusplus` is not defined.
-WARN_CFLAGS += -Wno-undef
-
-BUILD_FLAGS=CC="$(CC)" \
-               CFLAGS="$(GLIB_CFLAGS) $(AM_CFLAGS) $(CFLAGS) $(WARN_CFLAGS)" \
-               CPPFLAGS="$(AM_CPPFLAGS) $(CPPFLAGS) -I$(srcdir)/bt2" \
-               LDFLAGS="$(AM_LDFLAGS) $(LDFLAGS) $(GLIB_LIBS) $(PYTHON_LDFLAGS) $(LIBS)"
+BUILD_FLAGS= \
+       CC="$(CC)" \
+       CXX="$(CXX)" \
+       CXXFLAGS="$(GLIB_CFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(WARN_CXXFLAGS)" \
+       CPPFLAGS="$(AM_CPPFLAGS) $(CPPFLAGS) -I$(srcdir)/bt2" \
+       LDFLAGS="$(AM_LDFLAGS) $(LDFLAGS) $(GLIB_LIBS) $(PYTHON_LDFLAGS) $(LIBS)"
 
 SETUP_PY=$(BUILD_FLAGS) $(PYTHON) $(builddir)/setup.py
 
@@ -164,8 +158,8 @@ swig_verbose = $(swig_verbose_@AM_V@)
 swig_verbose_ = $(swig_verbose_@AM_DEFAULT_V@)
 swig_verbose_0 = @echo "  SWIG     " $@;
 
-$(builddir)/bt2/native_bt.c: $(SWIG_INTERFACE_FILES)
-       $(swig_verbose)$(SWIG) -MD -python -I"$(top_srcdir)/include" -o "$@" "$<"
+$(builddir)/bt2/native_bt.cpp: $(SWIG_INTERFACE_FILES)
+       $(swig_verbose)$(SWIG) -c++ -MD -python -I"$(top_srcdir)/include" -o "$@" "$<"
 
 -include bt2/native_bt.d
 
@@ -214,7 +208,7 @@ EXTRA_DIST = $(STATIC_BINDINGS_DEPS) $(SWIG_INTERFACE_FILES) $(STATIC_NATIVE_LIB
 # clean: generated C and Python files (by SWIG)
 CLEANFILES = \
        build-python-bindings.stamp \
-       bt2/native_bt.c \
+       bt2/native_bt.cpp \
        bt2/native_bt.d \
        bt2/native_bt.py \
        copy-static-deps.stamp
diff --git a/src/bindings/python/bt2/bt2/logging.c b/src/bindings/python/bt2/bt2/logging.c
deleted file mode 100644 (file)
index 1855d0e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * SPDX-License-Identifier: MIT
- *
- * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
- */
-
-#define BT_LOG_OUTPUT_LEVEL bt_python_bindings_bt2_log_level
-#include "logging/log.h"
-
-BT_LOG_INIT_LOG_LEVEL(bt_python_bindings_bt2_log_level,
-       "BABELTRACE_PYTHON_BT2_LOG_LEVEL");
diff --git a/src/bindings/python/bt2/bt2/logging.cpp b/src/bindings/python/bt2/bt2/logging.cpp
new file mode 100644 (file)
index 0000000..c20f292
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
+ */
+
+#define BT_LOG_OUTPUT_LEVEL bt_python_bindings_bt2_log_level
+#include "logging/log.h"
+
+BT_LOG_INIT_LOG_LEVEL(bt_python_bindings_bt2_log_level, "BABELTRACE_PYTHON_BT2_LOG_LEVEL");
diff --git a/src/bindings/python/bt2/bt2/logging.h b/src/bindings/python/bt2/bt2/logging.h
deleted file mode 100644 (file)
index 9a4efeb..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * SPDX-License-Identifier: MIT
- *
- * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
- */
-
-#ifndef BABELTRACE_BINDINGS_PYTHON_BT2_BT2_LOGGING_H
-#define BABELTRACE_BINDINGS_PYTHON_BT2_BT2_LOGGING_H
-
-#define BT_LOG_OUTPUT_LEVEL bt_python_bindings_bt2_log_level
-#include "logging/log.h"
-
-BT_LOG_LEVEL_EXTERN_SYMBOL(bt_python_bindings_bt2_log_level);
-
-#endif /* BABELTRACE_BINDINGS_PYTHON_BT2_BT2_LOGGING_H */
diff --git a/src/bindings/python/bt2/bt2/logging.hpp b/src/bindings/python/bt2/bt2/logging.hpp
new file mode 100644 (file)
index 0000000..d26d7c7
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
+ */
+
+#ifndef BABELTRACE_BINDINGS_PYTHON_BT2_BT2_LOGGING_HPP
+#define BABELTRACE_BINDINGS_PYTHON_BT2_BT2_LOGGING_HPP
+
+#define BT_LOG_OUTPUT_LEVEL bt_python_bindings_bt2_log_level
+#include "logging/log.h"
+
+BT_LOG_LEVEL_EXTERN_SYMBOL(bt_python_bindings_bt2_log_level);
+
+#endif /* BABELTRACE_BINDINGS_PYTHON_BT2_BT2_LOGGING_HPP */
index 5914f7025bd0f824088363fc574eda47555ec68f..f2b0bebb9660fcc3bff49059c022588c1cdf40a7 100644 (file)
@@ -12,7 +12,7 @@
 
 %{
 #define BT_LOG_TAG "BT2-PY"
-#include "logging.h"
+#include "logging.hpp"
 
 /*
  * Include before `<babeltrace2/func-status.h>` because
@@ -59,7 +59,7 @@ typedef uint64_t bt_listener_id;
  * functions on which we apply this typemap don't guarantee that the value of
  * `temp_value` will be unchanged or valid.
  */
-%typemap(in, numinputs=0) (const char **) (char *temp_value = (void *) 1) {
+%typemap(in, numinputs=0) (const char **) (char *temp_value = reinterpret_cast<char *>(1)) {
        $1 = &temp_value;
 }
 
@@ -248,6 +248,8 @@ void bt_bt2_exit_handler(void);
  * This function is defined by SWIG.  Declare here to avoid a
  * -Wmissing-prototypes warning.
  */
-PyObject *SWIG_init(void);
+extern "C" {
+       PyObject *SWIG_init(void);
+}
 
 %}
index f1629efb957d2b6264e5bb3c13df8839d25967c4..5b856b69fa1a08af2ab21b43985fb73119d57600 100644 (file)
@@ -115,8 +115,8 @@ bt_value *bt_bt2_auto_discover_source_components(const bt_value *inputs,
        }
 
        for (i = 0; i < auto_disc.results->len; i++) {
-               struct auto_source_discovery_result *autodisc_result =
-                       g_ptr_array_index(auto_disc.results, i);
+               const auto autodisc_result = static_cast<auto_source_discovery_result*>(
+                       g_ptr_array_index(auto_disc.results, i));
                bt_value_array_append_element_status append_element_status;
 
                component_info = bt_value_array_create();
index de11581adf2cafb3fc0e485641e0e6bd9c83e043..7c93580f848f448753a3734ba74113e97b2fb82b 100644 (file)
@@ -255,7 +255,8 @@ bt_component_class_initialize_method_status component_class_init(
                BT_COMP_LOG_CUR_LVL(BT_LOG_WARNING, log_level, self_component,
                        "Failed to call Python class's _bt_init_from_native() method: "
                        "py-cls-addr=%p", py_cls);
-               status = py_exc_to_status_component_clear(self_component);
+               status = static_cast<bt_component_class_initialize_method_status>(
+                       py_exc_to_status_component_clear(self_component));
                goto end;
        }
 
@@ -333,8 +334,8 @@ component_class_get_supported_mip_versions(
                        (enum bt_log_level) log_level, BT_LOG_TAG,
                        "Failed to call Python class's _bt_get_supported_mip_versions_from_native() method: "
                        "py-cls-addr=%p", py_cls);
-               status = py_exc_to_status_component_class_clear(self_component_class,
-                       log_level);
+               status = static_cast<bt_component_class_get_supported_mip_versions_method_status>(
+                       py_exc_to_status_component_class_clear(self_component_class, log_level));
                goto end;
        }
 
@@ -343,7 +344,8 @@ component_class_get_supported_mip_versions(
         * (PyLong) containing the address of a BT unsigned integer
         * range set object (new reference).
         */
-       ret_range_set = PyLong_AsVoidPtr(py_range_set_addr);
+       ret_range_set = static_cast<bt_integer_range_set_unsigned *>(
+               PyLong_AsVoidPtr(py_range_set_addr));
        BT_ASSERT(!PyErr_Occurred());
        BT_ASSERT(ret_range_set);
 
@@ -485,7 +487,8 @@ bt_component_class_initialize_method_status component_class_sink_init(
 static
 void component_class_finalize(bt_self_component *self_component)
 {
-       PyObject *py_comp = bt_self_component_get_data(self_component);
+       const auto py_comp = static_cast<PyObject *>(
+               bt_self_component_get_data(self_component));
        PyObject *py_method_result;
 
        BT_ASSERT(py_comp);
@@ -642,17 +645,18 @@ bt_message_iterator_class_can_seek_beginning_method_status
 component_class_can_seek_beginning(
                bt_self_message_iterator *self_message_iterator, bt_bool *can_seek)
 {
-       PyObject *py_iter;
        PyObject *py_result = NULL;
        bt_message_iterator_class_can_seek_beginning_method_status status;
-       py_iter = bt_self_message_iterator_get_data(self_message_iterator);
+       const auto py_iter = static_cast<PyObject *>(
+               bt_self_message_iterator_get_data(self_message_iterator));
 
        BT_ASSERT(py_iter);
 
        py_result = PyObject_CallMethod(py_iter,
                "_bt_can_seek_beginning_from_native", NULL);
        if (!py_result) {
-               status = py_exc_to_status_message_iterator_clear(self_message_iterator);
+               status = static_cast<bt_message_iterator_class_can_seek_beginning_method_status>(
+                       py_exc_to_status_message_iterator_clear(self_message_iterator));
                goto end;
        }
 
@@ -671,18 +675,19 @@ static
 bt_message_iterator_class_seek_beginning_method_status
 component_class_seek_beginning(bt_self_message_iterator *self_message_iterator)
 {
-       PyObject *py_iter;
        PyObject *py_result;
        bt_message_iterator_class_seek_beginning_method_status status;
+       const auto py_iter = static_cast<PyObject *>(
+               bt_self_message_iterator_get_data(self_message_iterator));
 
-       py_iter = bt_self_message_iterator_get_data(self_message_iterator);
        BT_ASSERT(py_iter);
 
        py_result = PyObject_CallMethod(py_iter,
                "_bt_seek_beginning_from_native",
                NULL);
        if (!py_result) {
-               status = py_exc_to_status_message_iterator_clear(self_message_iterator);
+               status = static_cast<bt_message_iterator_class_seek_beginning_method_status>(
+                       py_exc_to_status_message_iterator_clear(self_message_iterator));
                goto end;
        }
 
@@ -702,17 +707,18 @@ component_class_can_seek_ns_from_origin(
                bt_self_message_iterator *self_message_iterator,
                int64_t ns_from_origin, bt_bool *can_seek)
 {
-       PyObject *py_iter;
        PyObject *py_result = NULL;
        bt_message_iterator_class_can_seek_ns_from_origin_method_status status;
+       const auto py_iter = static_cast<PyObject *>(
+               bt_self_message_iterator_get_data(self_message_iterator));
 
-       py_iter = bt_self_message_iterator_get_data(self_message_iterator);
        BT_ASSERT(py_iter);
 
        py_result = PyObject_CallMethod(py_iter,
                "_bt_can_seek_ns_from_origin_from_native", "L", ns_from_origin);
        if (!py_result) {
-               status = py_exc_to_status_message_iterator_clear(self_message_iterator);
+               status = static_cast<bt_message_iterator_class_can_seek_ns_from_origin_method_status>(
+                       py_exc_to_status_message_iterator_clear(self_message_iterator));
                goto end;
        }
 
@@ -733,17 +739,18 @@ component_class_seek_ns_from_origin(
                bt_self_message_iterator *self_message_iterator,
                int64_t ns_from_origin)
 {
-       PyObject *py_iter;
        PyObject *py_result;
        bt_message_iterator_class_seek_ns_from_origin_method_status status;
+       const auto py_iter = static_cast<PyObject *>(
+               bt_self_message_iterator_get_data(self_message_iterator));
 
-       py_iter = bt_self_message_iterator_get_data(self_message_iterator);
        BT_ASSERT(py_iter);
 
        py_result = PyObject_CallMethod(py_iter,
                "_bt_seek_ns_from_origin_from_native", "L", ns_from_origin);
        if (!py_result) {
-               status = py_exc_to_status_message_iterator_clear(self_message_iterator);
+               status = static_cast<bt_message_iterator_class_seek_ns_from_origin_method_status>(
+                       py_exc_to_status_message_iterator_clear(self_message_iterator));
                goto end;
        }
 
@@ -768,21 +775,21 @@ bt_component_class_port_connected_method_status component_class_port_connected(
                swig_type_info *other_port_swig_type)
 {
        bt_component_class_port_connected_method_status status;
-       PyObject *py_comp = NULL;
        PyObject *py_self_port_ptr = NULL;
        PyObject *py_other_port_ptr = NULL;
        PyObject *py_method_result = NULL;
        bt_logging_level log_level = get_self_component_log_level(
                self_component);
+       const auto py_comp = static_cast<PyObject *>(
+               bt_self_component_get_data(self_component));
 
-       py_comp = bt_self_component_get_data(self_component);
        BT_ASSERT(py_comp);
        py_self_port_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(self_component_port),
                self_component_port_swig_type, 0);
        if (!py_self_port_ptr) {
                BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
                        BT_FMT_SWIG_ALLOC_FAILED);
-               status = __BT_FUNC_STATUS_MEMORY_ERROR;
+               status = BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
                goto end;
        }
 
@@ -791,7 +798,7 @@ bt_component_class_port_connected_method_status component_class_port_connected(
        if (!py_other_port_ptr) {
                BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, log_level, self_component,
                        BT_FMT_SWIG_ALLOC_FAILED);
-               status = __BT_FUNC_STATUS_MEMORY_ERROR;
+               status = BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
                goto end;
        }
 
@@ -799,7 +806,8 @@ bt_component_class_port_connected_method_status component_class_port_connected(
                "_bt_port_connected_from_native", "(OiO)", py_self_port_ptr,
                self_component_port_type, py_other_port_ptr);
        if (!py_method_result) {
-               status = py_exc_to_status_component_clear(self_component);
+               status = static_cast<bt_component_class_port_connected_method_status>(
+                       py_exc_to_status_component_clear(self_component));
                goto end;
        }
 
@@ -892,17 +900,17 @@ bt_component_class_sink_graph_is_configured_method_status
 component_class_sink_graph_is_configured(
                bt_self_component_sink *self_component_sink)
 {
-       PyObject *py_comp = NULL;
        PyObject *py_method_result = NULL;
        bt_component_class_sink_graph_is_configured_method_status status;
        bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
-
-       py_comp = bt_self_component_get_data(self_component);
+       const auto py_comp = static_cast<PyObject *>(
+               bt_self_component_get_data(self_component));
 
        py_method_result = PyObject_CallMethod(py_comp,
                "_bt_graph_is_configured_from_native", NULL);
        if (!py_method_result) {
-               status = py_exc_to_status_component_clear(self_component);
+               status = static_cast<bt_component_class_sink_graph_is_configured_method_status>(
+                       py_exc_to_status_component_clear(self_component));
                goto end;
        }
 
@@ -929,7 +937,8 @@ bt_component_class_query_method_status component_class_query(
        PyObject *py_query_func = NULL;
        PyObject *py_object = NULL;
        PyObject *py_results_addr = NULL;
-       bt_component_class_query_method_status status = __BT_FUNC_STATUS_OK;
+       bt_component_class_query_method_status status =
+               BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_OK;
        const bt_query_executor *query_exec =
                bt_private_query_executor_as_query_executor_const(
                        priv_query_executor);
@@ -992,8 +1001,8 @@ bt_component_class_query_method_status component_class_query(
                py_object, py_params_ptr,
                method_data ? method_data : Py_None);
        if (!py_results_addr) {
-               status = py_exc_to_status_component_class_clear(self_component_class,
-                       log_level);
+               status = static_cast<bt_component_class_query_method_status>(
+                       py_exc_to_status_component_class_clear(self_component_class, log_level));
                if (status < 0) {
 #define BT_FMT "Failed to call Python class's _bt_query_from_native() method: py-cls-addr=%p"
                        BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_WARNING,
@@ -1011,14 +1020,14 @@ bt_component_class_query_method_status component_class_query(
         * (PyLong) containing the address of a BT value object (new
         * reference).
         */
-       *result = PyLong_AsVoidPtr(py_results_addr);
+       *result = static_cast<const bt_value *>(PyLong_AsVoidPtr(py_results_addr));
        BT_ASSERT(!PyErr_Occurred());
        BT_ASSERT(*result);
        goto end;
 
 error:
        PyErr_Clear();
-       status = __BT_FUNC_STATUS_ERROR;
+       status = BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
 
 end:
        Py_XDECREF(py_params_ptr);
@@ -1081,7 +1090,8 @@ component_class_message_iterator_init(
                bt_self_message_iterator_configuration *config,
                bt_self_component_port_output *self_component_port_output)
 {
-       bt_message_iterator_class_initialize_method_status status = __BT_FUNC_STATUS_OK;
+       bt_message_iterator_class_initialize_method_status status =
+               BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK;
        PyObject *py_comp_cls = NULL;
        PyObject *py_iter_cls = NULL;
        PyObject *py_iter_ptr = NULL;
@@ -1089,14 +1099,13 @@ component_class_message_iterator_init(
        PyObject *py_component_port_output_ptr = NULL;
        PyObject *py_init_method_result = NULL;
        PyObject *py_iter = NULL;
-       PyObject *py_comp;
        bt_self_component *self_component =
                bt_self_message_iterator_borrow_component(
                        self_message_iterator);
        bt_logging_level log_level = get_self_component_log_level(
                self_component);
-
-       py_comp = bt_self_component_get_data(self_component);
+       const auto py_comp = static_cast<PyObject *>(
+               bt_self_component_get_data(self_component));
 
        /* Find user's Python message iterator class */
        py_comp_cls = PyObject_GetAttrString(py_comp, "__class__");
@@ -1204,12 +1213,13 @@ component_class_message_iterator_init(
 
 python_error:
        /* Handling of errors that cause a Python exception to be set. */
-       status = py_exc_to_status_message_iterator_clear(self_message_iterator);
+       status = static_cast<bt_message_iterator_class_initialize_method_status>(
+               py_exc_to_status_message_iterator_clear(self_message_iterator));
        goto end;
 
 error:
        /* Handling of errors that don't cause a Python exception to be set. */
-       status = __BT_FUNC_STATUS_ERROR;
+       status = BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
 
 end:
        BT_ASSERT(!PyErr_Occurred());
@@ -1228,8 +1238,8 @@ static
 void component_class_message_iterator_finalize(
                bt_self_message_iterator *message_iterator)
 {
-       PyObject *py_message_iter = bt_self_message_iterator_get_data(
-               message_iterator);
+       const auto py_message_iter = static_cast<PyObject *>(
+               bt_self_message_iterator_get_data(message_iterator));
        PyObject *py_method_result = NULL;
 
        BT_ASSERT(py_message_iter);
@@ -1269,14 +1279,16 @@ component_class_message_iterator_next(
                uint64_t *count)
 {
        bt_message_iterator_class_next_method_status status;
-       PyObject *py_message_iter = bt_self_message_iterator_get_data(message_iterator);
+       const auto py_message_iter = static_cast<PyObject *>(
+               bt_self_message_iterator_get_data(message_iterator));
        PyObject *py_method_result = NULL;
 
        BT_ASSERT_DBG(py_message_iter);
        py_method_result = PyObject_CallMethod(py_message_iter,
                "_bt_next_from_native", NULL);
        if (!py_method_result) {
-               status = py_exc_to_status_message_iterator_clear(message_iterator);
+               status = static_cast<bt_message_iterator_class_next_method_status>(
+                       py_exc_to_status_message_iterator_clear(message_iterator));
                goto end;
        }
 
@@ -1285,7 +1297,7 @@ component_class_message_iterator_next(
         * (PyLong) containing the address of a native message
         * object (which is now ours).
         */
-       msgs[0] = PyLong_AsVoidPtr(py_method_result);
+       msgs[0] = static_cast<const bt_message *>(PyLong_AsVoidPtr(py_method_result));
        *count = 1;
 
        /* Overflow errors should never happen. */
@@ -1303,7 +1315,7 @@ bt_component_class_sink_consume_method_status
 component_class_sink_consume(bt_self_component_sink *self_component_sink)
 {
        bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
-       PyObject *py_comp = bt_self_component_get_data(self_component);
+       const auto py_comp = static_cast<PyObject *>(bt_self_component_get_data(self_component));
        PyObject *py_method_result = NULL;
        bt_component_class_sink_consume_method_status status;
 
@@ -1312,7 +1324,8 @@ component_class_sink_consume(bt_self_component_sink *self_component_sink)
        py_method_result = PyObject_CallMethod(py_comp,
                "_user_consume", NULL);
        if (!py_method_result) {
-               status = py_exc_to_status_component_clear(self_component);
+               status = static_cast<bt_component_class_sink_consume_method_status>(
+                       py_exc_to_status_component_clear(self_component));
                goto end;
        }
 
index b7f05bb8715b79be2e45c0d7c7715fd9fd013efa..a046dd86cff56753eb8ba0fb0ed150cae0592390 100644 (file)
@@ -9,7 +9,7 @@
  */
 %typemap(in, numinputs=0)
        (bt_event_class_log_level *)
-       (bt_event_class_log_level temp = -1) {
+       (bt_event_class_log_level temp = static_cast<bt_event_class_log_level>(-1)) {
        $1 = &temp;
 }
 
index 8831e21ad7667c1445b6dfe449bf0d8f2d252e18..dd51df3050e99ddb6cf763f317869d7c48ec0738 100644 (file)
@@ -24,29 +24,29 @@ static bt_graph_listener_func_status port_added_listener(
        py_component_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(component), component_swig_type, 0);
        if (!py_component_ptr) {
                BT_LOGF_STR("Failed to create component SWIG pointer object.");
-               status = __BT_FUNC_STATUS_MEMORY_ERROR;
+               status = BT_GRAPH_LISTENER_FUNC_STATUS_MEMORY_ERROR;
                goto end;
        }
 
        py_port_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(port), port_swig_type, 0);
        if (!py_port_ptr) {
                BT_LOGF_STR("Failed to create port SWIG pointer object.");
-               status = __BT_FUNC_STATUS_MEMORY_ERROR;
+               status = BT_GRAPH_LISTENER_FUNC_STATUS_MEMORY_ERROR;
                goto end;
        }
 
-       py_res = PyObject_CallFunction(py_callable, "(OiOi)",
+       py_res = PyObject_CallFunction(static_cast<PyObject *>(py_callable), "(OiOi)",
                py_component_ptr, component_class_type, py_port_ptr, port_type);
        if (!py_res) {
                loge_exception_append_cause_clear(
                        "Graph's port added listener (Python)",
                        BT_LOG_OUTPUT_LEVEL);
-               status = __BT_FUNC_STATUS_ERROR;
+               status = BT_GRAPH_LISTENER_FUNC_STATUS_ERROR;
                goto end;
        }
 
        BT_ASSERT(py_res == Py_None);
-       status = __BT_FUNC_STATUS_OK;
+       status = BT_GRAPH_LISTENER_FUNC_STATUS_OK;
 
 end:
        Py_XDECREF(py_res);
index aaa88fca8a8b893455458bd8909062f25051fa75..13b9a093d033ac0d01c9694ae05a14d4a34c2de4 100644 (file)
@@ -51,10 +51,12 @@ static PyObject *bt_bt2_get_user_component_from_user_msg_iter(
                bt_self_message_iterator *self_message_iterator)
 {
        bt_self_component *self_component = bt_self_message_iterator_borrow_component(self_message_iterator);
-       PyObject *py_comp;
 
        BT_ASSERT_DBG(self_component);
-       py_comp = bt_self_component_get_data(self_component);
+
+       const auto py_comp = static_cast<PyObject *>(
+               bt_self_component_get_data(self_component));
+
        BT_ASSERT_DBG(py_comp);
 
        /* Return new reference */
index 1a0a50a50a5b232c81a0179282e44376ab0fdd63..c0b72076e12bca11712b22d073b8f0d054340992 100644 (file)
@@ -14,7 +14,7 @@
 
 %typemap(out) void * {
        Py_INCREF($1);
-       $result = $1;
+       $result = static_cast<PyObject *>($1);
 }
 
 %include <babeltrace2/graph/port.h>
index bccdf87584b757cb148e0702bb8331ec976aac7a..f6dd64e017054df7e9d1878ddd81fb70099eea1b 100644 (file)
@@ -20,7 +20,8 @@ trace_destroyed_listener(const bt_trace *trace, void *py_callable)
                bt_common_abort();
        }
 
-       py_res = PyObject_CallFunction(py_callable, "(O)", py_trace_ptr);
+       py_res = PyObject_CallFunction(static_cast<PyObject *>(py_callable), "(O)",
+               py_trace_ptr);
        if (!py_res) {
                logw_exception_clear(BT_LOG_OUTPUT_LEVEL);
                goto end;
index 201801da4b5f87836f932f69c022014a31a2b2aa..3f293086fdd8ce03a2e0238e613716a427923541 100644 (file)
@@ -20,7 +20,8 @@ trace_class_destroyed_listener(const bt_trace_class *trace_class, void *py_calla
                bt_common_abort();
        }
 
-       py_res = PyObject_CallFunction(py_callable, "(O)", py_trace_class_ptr);
+       py_res = PyObject_CallFunction(static_cast<PyObject *>(py_callable), "(O)",
+               py_trace_class_ptr);
        if (!py_res) {
                logw_exception_clear(BT_LOG_OUTPUT_LEVEL);
                goto end;
index 650515f3a7949edab58fc9de6f98651067568b7d..c391aa9cb232ed2e00e7d20f9ba46a9e5d04cc80 100644 (file)
@@ -14,13 +14,13 @@ struct bt_value_map_get_keys_data {
 static bt_value_map_foreach_entry_const_func_status bt_value_map_get_keys_cb(
                const char *key, const struct bt_value *object, void *data)
 {
-       int status;
-       struct bt_value_map_get_keys_data *priv_data = data;
+       const auto priv_data = static_cast<bt_value_map_get_keys_data *>(data);
+       bt_value_array_append_element_status status =
+               bt_value_array_append_string_element(priv_data->keys, key);
 
-       status = bt_value_array_append_string_element(priv_data->keys, key);
-       BT_ASSERT(status == __BT_FUNC_STATUS_OK ||
-               status == __BT_FUNC_STATUS_MEMORY_ERROR);
-       return status;
+       BT_ASSERT(status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK ||
+               status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_MEMORY_ERROR);
+       return static_cast<bt_value_map_foreach_entry_const_func_status>(status);
 }
 
 static struct bt_value *bt_value_map_get_keys(const struct bt_value *map_obj)
index 411f715b2edc5db7ba32323120cba05a350de0e9..a8059aed6b2d34922bc61fe41889a5ef5f3bbd5f 100644 (file)
@@ -11,8 +11,11 @@ import subprocess
 # Distutils was removed in Python 3.12, use setuptools as an alternative.
 if sys.version_info >= (3, 12):
     from setuptools import setup, Extension
+    from setuptools.command.build_ext import build_ext
 else:
     from distutils.core import setup, Extension
+    from distutils.command.build_ext import build_ext
+
 
 # Starting with Debian's Python 3.10, the default install scheme is
 # 'posix_local' which is a Debian specific scheme based on 'posix_prefix' but
@@ -59,10 +62,6 @@ def getenv_assert(name: str):
     return value
 
 
-def get_cflags():
-    return getenv_assert("CFLAGS")
-
-
 # distutils performs a similar transformation step on LDSHARED on
 # darwin to use the overridden CC as the default command for LDSHARED
 # (see distutils' customize_compiler() step in the sysconfig module).
@@ -85,7 +84,6 @@ def get_ldshared():
 
 def our_get_config_vars(*args):
     overridden_config_vars_funcs = {
-        "CFLAGS": get_cflags,
         "LDSHARED": get_ldshared,
     }
 
@@ -126,27 +124,73 @@ def cygpath_m(path: str):
     return path
 
 
-# On MinGW systems, check CFLAGS and CPPFLAGS for absolute include paths
-# (starts with '-I/') and convert them to valid Windows paths using cygpath.
-if is_mingw():
-    for flagvar in ["CFLAGS", "CPPFLAGS"]:
-        cur_flags = getenv_assert(flagvar)
-        new_flags = ""
-        for flag in cur_flags.split():
-            if flag.startswith("-I/"):
-                flag = "-I{}".format(cygpath_m(flag[2:]))
+# On MinGW systems, convert absolute include paths (starting with '-I/')
+# in 'flags' to valid Windows paths using cygpath. On other systems,
+# return 'flags' as-is.
+def transform_include_paths_if_mingw(flags: str):
+    if not is_mingw():
+        return flags
+
+    return " ".join(
+        (
+            "-I{}".format(cygpath_m(flag[2:])) if flag.startswith("-I/") else flag
+            for flag in flags.split()
+        )
+    )
 
-            new_flags += " {}".format(flag)
 
-        os.environ[flagvar] = new_flags
+class custom_build_ext(build_ext):
+    def build_extensions(self):
+        # There are multiple issues handled simultaneously here:
+        #
+        #  - distutils (at least before setuptools 72.2.0) doesn't
+        #    handle well building shared objects from C++ source files.
+        #    It will attempt to compile them using the C compiler. Set
+        #    the executable used to compile C++ source files that will
+        #    end up in shared objects so that it uses the C++ compiler
+        #    defined by the `CXX` environment variable.
+        #
+        #  - The CPPFLAGS and CXXFLAGS provided by sysconfig may not
+        #    work with the compiler we tell distutils to use. We
+        #    therefore also force our own flags (the call to
+        #    `set_executable()` below overrides any flags previously
+        #    found by distutils).
+        #
+        #   - On MSYS2, some include paths need to be converted from
+        #     Unix to Windows form.
+
+        cxxflags = transform_include_paths_if_mingw(getenv_assert("CXXFLAGS"))
+        cppflags = transform_include_paths_if_mingw(getenv_assert("CPPFLAGS"))
+        cxx = getenv_assert("CXX")
+
+        self.compiler.set_executable(
+            (
+                # setuptools >= 72.2.0 uses the `compiler_so_cxx`
+                # attribute:
+                #
+                #   https://github.com/pypa/setuptools/commit/2c937116cc0dcd9b26b6070e89a3dc5dcbedc2ae
+                #
+                # This version of setuptools seems to have better support
+                # for building shared objects from C++ source files, but
+                # we override the executable anyway, for consistency.
+                "compiler_so_cxx"
+                if hasattr(self.compiler, "compiler_so_cxx")
+                else "compiler_so"
+            ),
+            "{} {} {} {}".format(
+                cxx, sysconfig.get_config_var("CCSHARED"), cxxflags, cppflags
+            ),
+        )
+
+        super().build_extensions()
 
 
 def main():
     babeltrace_ext = Extension(
         "bt2._native_bt",
         sources=[
-            "bt2/native_bt.c",
-            cygpath_m("@srcdir@/bt2/logging.c"),
+            "bt2/native_bt.cpp",
+            cygpath_m("@srcdir@/bt2/logging.cpp"),
         ],
         libraries=["babeltrace2", "glib-2.0"],
         extra_objects=[
@@ -177,6 +221,7 @@ def main():
             "License :: OSI Approved :: The MIT License",
             "Programming Language :: Python :: 3" "Topic :: System :: Logging",
         ],
+        cmdclass={"build_ext": custom_build_ext},
     )
 
     # After the installation, we check that the install directory is included in
index 6ba19590be59baddbaf479178a5ae69e0dc942cc..cb64a640b1f197eb3587233f1e2224842485a211 100644 (file)
 
 #include "common/macros.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * Formats the Python traceback `py_exc_tb` using traceback.format_tb, from the
  * Python standard library, and return it as a Gstring.
@@ -46,4 +50,8 @@ GString *bt_py_common_format_exception(PyObject *py_exc_type,
  */
 GString *bt_py_common_format_current_exception(int log_level);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* BABELTRACE_PY_COMMON_PY_COMMON_H */
index 799c397fd598f1a92d9e170e808ef7ba7826f8a0..5380f18ec1d57edeacdabb0d5c5caffe23d1f2b5 100644 (file)
 #include <common/macros.h>
 #include <glib.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 gchar *format_bt_error_cause(
                const bt_error_cause *error_cause,
                unsigned int columns,
@@ -24,4 +28,8 @@ gchar *format_bt_error(
                bt_logging_level log_level,
                enum bt_common_color_when use_colors);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* BABELTRACE_STRING_FORMAT_FORMAT_ERROR_H */
This page took 0.040465 seconds and 4 git commands to generate.