[vlc-commits] [Git][videolan/vlc][master] 3 commits: libvlc.h: ensure the header is correctly exposed to C++
Thomas Guillem (@tguillem)
gitlab at videolan.org
Fri Dec 22 13:26:12 UTC 2023
Thomas Guillem pushed to branch master at VideoLAN / VLC
Commits:
1701e2da by Alexandre Janniaux at 2023-12-22T13:00:09+00:00
libvlc.h: ensure the header is correctly exposed to C++
The header is not public but can be used by tests in C++.
- - - - -
6cfbabfc by Alexandre Janniaux at 2023-12-22T13:00:09+00:00
vlc_objects: expose wrappers around vlc_object_create/delete
Using placement new and manual call to the destructor. It ensures that
C++ objects are correctly handled when creating C++ objects through
vlc_object_create<>(), and that their destructors are correctly called
when the (C++) object is destroyed.
According to the C++ draft standard, the vlc_object_t won't get
overwritten by the placement new since (7.1) will apply to the C++
object being allocated and placement-new'ed, which triggers the default
initialization of members, and the default initialization of the
vlc_object_t member enters the (7.3) case since no constructors exists
for the structure. (It's an extern "C" structure).
To default-initialize an object of type T means:
(7.1)
If T is a (possibly cv-qualified) class type ([class]), constructors are considered.
The applicable constructors are enumerated ([over.match.ctor]), and the best one for the initializer () is chosen through overload resolution ([over.match]).
The constructor thus selected is called, with an empty argument list, to initialize the object.
(7.2)
If T is an array type, each element is default-initialized.
(7.3)
Otherwise, no initialization is performed.
--: https://eel.is/c++draft/dcl.init#general-7
However, it's not possible to use a zero-initializing placement-new
operation.
- - - - -
dbe399b5 by Alexandre Janniaux at 2023-12-22T13:00:09+00:00
objects: add test for C++ wrappers
The test is exposing a stub var_DestroyAll() because object.c is
link-dependant to this symbol, but no variable is created anyway.
It's also checking that the vlc_object_t member doesn't get overwritten.
- - - - -
4 changed files:
- include/vlc_objects.h
- src/Makefile.am
- src/libvlc.h
- + src/misc/objects_cxx_test.cpp
Changes:
=====================================
include/vlc_objects.h
=====================================
@@ -24,6 +24,7 @@
#define VLC_OBJECTS_H 1
#ifdef __cplusplus
+#include <new>
extern "C" {
#endif
@@ -314,8 +315,22 @@ template<typename T, typename O> VLC_MALLOC VLC_USED
static inline T* vlc_object_create(O *obj)
{
static_assert(std::is_pointer<T>::value == false, "vlc_object_create can only create objects");
- return static_cast<T*>(vlc_object_create(VLC_OBJECT(obj), sizeof(T)));
+ void *object = vlc_object_create(VLC_OBJECT(obj), sizeof(T));
+ if (object == nullptr)
+ return nullptr;
+
+ return new(object) T;
}
+
+#undef vlc_object_delete
+template<typename O>
+static inline void vlc_object_delete(O *obj)
+{
+ if (!std::is_trivially_destructible<O>::value)
+ obj->~O();
+ vlc_object_delete(VLC_OBJECT(obj));
+}
+
#endif
/** @} */
=====================================
src/Makefile.am
=====================================
@@ -612,6 +612,7 @@ check_PROGRAMS = \
test_jaro_winkler \
test_list \
test_md5 \
+ test_objects_cxx \
test_picture_pool \
test_sort \
test_timer \
@@ -642,6 +643,7 @@ test_interrupt_LDADD = $(LDADD) $(LIBS_libvlccore)
test_jaro_winkler_SOURCES = test/jaro_winkler.c config/jaro_winkler.c
test_list_SOURCES = test/list.c
test_md5_SOURCES = test/md5.c
+test_objects_cxx_SOURCES = misc/objects_cxx_test.cpp misc/objects.c
test_picture_pool_SOURCES = test/picture_pool.c
test_sort_SOURCES = test/sort.c
test_timer_SOURCES = test/timer.c
=====================================
src/libvlc.h
=====================================
@@ -26,6 +26,10 @@
#include <vlc_input_item.h>
+# ifdef __cplusplus
+extern "C" {
+# endif
+
extern const char psz_vlc_changeset[];
typedef struct variable_t variable_t;
@@ -210,4 +214,8 @@ int vlc_MetadataRequest(libvlc_int_t *libvlc, input_item_t *item,
*/
void var_OptionParse (vlc_object_t *, const char *, bool trusted);
+# ifdef __cplusplus
+} // extern "C"
+# endif
+
#endif
=====================================
src/misc/objects_cxx_test.cpp
=====================================
@@ -0,0 +1,77 @@
+/*****************************************************************************
+ * objects_cxx_test.cpp: vlc_object_t helper tests
+ *****************************************************************************
+ * Copyright (C) 2023 Videlabs
+ *
+ * Authors: Alexandre Janniaux <ajanni at videolabs.io>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <vlc_common.h>
+#include <vlc_objects.h>
+
+#include "../libvlc.h"
+
+extern "C" {
+ void var_DestroyAll(vlc_object_t *) { /* stub */ }
+}
+
+struct ObjectType {
+ vlc_object_t obj;
+ int value = 5;
+ ~ObjectType() { destructor_called = true; }
+ static bool destructor_called;
+};
+bool ObjectType::destructor_called = false;
+
+int main(int argc, char **argv)
+{
+ (void)argc; (void)argv;
+
+ vlc_object_t *root = new vlc_object_t {};
+ int ret = vlc_object_init(root, nullptr, "root");
+ assert(ret == 0);
+
+ struct ObjectType *child = vlc_object_create<ObjectType>(root);
+
+ /* Ensure default constructor have been called. */
+ assert(child->value == 5);
+ assert(ObjectType::destructor_called == false);
+
+ /* No zero-initialization of the object itself. */
+ assert(child->obj.priv != NULL);
+
+ /* Ensure destructor have been called. */
+ vlc_object_delete(child);
+ assert(ObjectType::destructor_called == true);
+ ObjectType::destructor_called = false;
+
+ /* Ensure it's not called for C objects. */
+ ObjectType *child_c = static_cast<ObjectType*>(vlc_object_create(root, sizeof(ObjectType)));
+ assert(child_c->value == 0);
+ vlc_object_delete(VLC_OBJECT(child_c));
+ assert(ObjectType::destructor_called == false);
+
+ vlc_object_deinit(root);
+ delete(root);
+
+ return 0;
+}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/ca32e6b95fa6dfb2e2cc8b2b946d87df168dffa3...dbe399b593d76d722afadac8272d5939b4c20059
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/ca32e6b95fa6dfb2e2cc8b2b946d87df168dffa3...dbe399b593d76d722afadac8272d5939b4c20059
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list