From f8f072fb3d784419f357891ae6849241e4ed597f Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 14 Sep 2017 11:15:36 +0200 Subject: [PATCH] Handle C back pointer in C++ objects. --- src/c-wrapper/c-tools.h | 42 +++++++++++++++++++++++++++++----- src/object/clonable-object-p.h | 4 ++++ src/object/clonable-object.cpp | 16 +++++++++++++ src/object/clonable-object.h | 8 +++++++ src/variant/variant.h | 2 +- 5 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/c-wrapper/c-tools.h b/src/c-wrapper/c-tools.h index 0f4855089..4fbb27a49 100644 --- a/src/c-wrapper/c-tools.h +++ b/src/c-wrapper/c-tools.h @@ -22,6 +22,8 @@ #include #include +#include "variant/variant.h" + // From coreapi. #include "private.h" @@ -97,18 +99,21 @@ public: } template - static inline void setCppPtrFromC (void *object, std::shared_ptr &cppPtr) { + static inline void setCppPtrFromC (void *object, const std::shared_ptr &cppPtr) { L_ASSERT(object); static_cast *>(object)->cppPtr = cppPtr; + cppPtr->setProperty("LinphonePrivate::Wrapper::cBackPtr", object); } template - static inline void setCppPtrFromC (void *object, T *cppPtr) { + static inline void setCppPtrFromC (void *object, const T *cppPtr) { L_ASSERT(object); - T *tPtr = reinterpret_cast(static_cast *>(object)->cppPtr); - if (tPtr != cppPtr) { - delete tPtr; - static_cast *>(object)->cppPtr = new T(*cppPtr); + T *oldPtr = reinterpret_cast(static_cast *>(object)->cppPtr); + if (oldPtr != cppPtr) { + delete oldPtr; + T *cppObject = static_cast *>(object)->cppPtr; + cppObject = new T(*cppPtr); + cppObject->setProperty("LinphonePrivate::Wrapper::cBackPtr", object); } } @@ -122,6 +127,28 @@ public: return cppPtr; } + template + static inline CType * getCBackPtr (const std::shared_ptr &object, CType *(*cTypeAllocator)()) { + Variant v = object->getProperty("LinphonePrivate::Wrapper::cBackPtr"); + void *value = v.getValue(); + if (!value) { + CType *cObject = cTypeAllocator(); + setCppPtrFromC(cObject, object); + } + return reinterpret_cast(value); + } + + template + static inline CType * getCBackPtr (const CppType *object, CType *(*cTypeAllocator)()) { + Variant v = object->getProperty("LinphonePrivate::Wrapper::cBackPtr"); + void *value = v.getValue(); + if (!value) { + CType *cObject = cTypeAllocator(); + setCppPtrFromC(cObject, object); + } + return reinterpret_cast(value); + } + // --------------------------------------------------------------------------- template @@ -235,6 +262,9 @@ LINPHONE_END_NAMESPACE L_GET_CPP_PTR_FROM_C_STRUCT(OBJECT, CPP_TYPE, C_TYPE) \ )) +#define L_GET_C_BACK_PTR(OBJECT, C_TYPE, C_NAME) \ + LINPHONE_NAMESPACE::Wrapper::getCBackPtr(OBJECT, _linphone_ ## C_NAME ## _init) + #define L_GET_C_LIST_FROM_CPP_LIST(LIST, TYPE) \ LINPHONE_NAMESPACE::Wrapper::getCListFromCppList(LIST) #define L_GET_CPP_LIST_FROM_C_LIST(LIST, TYPE) \ diff --git a/src/object/clonable-object-p.h b/src/object/clonable-object-p.h index 7d507599f..87266a2c5 100644 --- a/src/object/clonable-object-p.h +++ b/src/object/clonable-object-p.h @@ -23,6 +23,8 @@ #include "linphone/utils/general.h" +#include "variant/variant.h" + // ============================================================================= LINPHONE_BEGIN_NAMESPACE @@ -41,6 +43,8 @@ private: int nRefs = 0; + std::unordered_map properties; + L_DECLARE_PUBLIC(ClonableObject); // It's forbidden to copy directly one Clonable object private. diff --git a/src/object/clonable-object.cpp b/src/object/clonable-object.cpp index 45412dc88..72a9f290d 100644 --- a/src/object/clonable-object.cpp +++ b/src/object/clonable-object.cpp @@ -82,4 +82,20 @@ void ClonableObject::setRef (const ClonableObjectPrivate &p) { mPrivate->ref(); } +Variant ClonableObject::getProperty (const string &name) const { + L_D(const ClonableObject); + auto it = d->properties.find(name); + return it == d->properties.cend() ? Variant() : it->second; +} + +void ClonableObject::setProperty (const string &name, const Variant &value) { + L_D(ClonableObject); + d->properties[name] = value; +} + +void ClonableObject::setProperty (const string &name, Variant &&value) { + L_D(ClonableObject); + d->properties[name] = move(value); +} + LINPHONE_END_NAMESPACE diff --git a/src/object/clonable-object.h b/src/object/clonable-object.h index 34d4771c6..e36c5add2 100644 --- a/src/object/clonable-object.h +++ b/src/object/clonable-object.h @@ -19,16 +19,24 @@ #ifndef _CLONABLE_OBJECT_H_ #define _CLONABLE_OBJECT_H_ +#include + #include "linphone/utils/general.h" // ============================================================================= LINPHONE_BEGIN_NAMESPACE +class Variant; + class LINPHONE_PUBLIC ClonableObject { public: virtual ~ClonableObject (); + Variant getProperty (const std::string &name) const; + void setProperty (const std::string &name, const Variant &value); + void setProperty (const std::string &name, Variant &&value); + protected: // Use a new ClonableObjectPrivate without owner. explicit ClonableObject (ClonableObjectPrivate &p); diff --git a/src/variant/variant.h b/src/variant/variant.h index 2966f79d1..4b1ffe529 100644 --- a/src/variant/variant.h +++ b/src/variant/variant.h @@ -82,7 +82,7 @@ public: template::value> > // void* constructor. Must be explicitly called. - Variant (T value); + Variant (T value) {} ~Variant ();