diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 83aad97d3..155d87db4 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -950,19 +950,20 @@ static void call_failure(SalOp *op){ case SalReasonRedirect: { linphone_call_stop_media_streams(call); - if ( call->state==LinphoneCallOutgoingInit - || call->state==LinphoneCallOutgoingProgress - || call->state==LinphoneCallOutgoingRinging /*push case*/ - || call->state==LinphoneCallOutgoingEarlyMedia){ - LinphoneAddress* redirection_to = (LinphoneAddress*)sal_op_get_remote_contact_address(call->op); - if( redirection_to ){ - char* url = linphone_address_as_string(redirection_to); + if ( + call->state == LinphoneCallOutgoingInit || + call->state == LinphoneCallOutgoingProgress || + call->state == LinphoneCallOutgoingRinging || + call->state == LinphoneCallOutgoingEarlyMedia + ) { + const SalAddress* redirection_to = sal_op_get_remote_contact_address(call->op); + if (redirection_to) { + char *url = sal_address_as_string(redirection_to); ms_warning("Redirecting call [%p] to %s",call, url); - ms_free(url); - if( call->log->to != NULL ) { + if (call->log->to) linphone_address_unref(call->log->to); - } - call->log->to = linphone_address_ref(redirection_to); + call->log->to = linphone_address_new(url); + ms_free(url); linphone_call_restart_invite(call); return; } diff --git a/coreapi/event.c b/coreapi/event.c index d5926dd96..559faf0a5 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -275,7 +275,7 @@ LinphoneStatus linphone_event_notify(LinphoneEvent *lev, const LinphoneContent * static LinphoneEvent *_linphone_core_create_publish(LinphoneCore *core, LinphoneProxyConfig *cfg, const LinphoneAddress *resource, const char *event, int expires){ LinphoneCore *lc = core; LinphoneEvent *lev; - + if (!lc && cfg) { if (cfg->lc) lc = cfg->lc; @@ -286,7 +286,7 @@ static LinphoneEvent *_linphone_core_create_publish(LinphoneCore *core, Linphone } if (!resource && cfg) resource = linphone_proxy_config_get_identity_address(cfg); - + lev = linphone_event_new(lc,LinphoneSubscriptionInvalidDir, event,expires); linphone_configure_op_with_proxy(lc,lev->op,resource,NULL,lp_config_get_int(lc->config,"sip","publish_msg_with_contact",0),cfg); sal_op_set_manual_refresher_mode(lev->op,!lp_config_get_int(lc->config,"sip","refresh_generic_publish",1)); @@ -296,10 +296,10 @@ LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddr return _linphone_core_create_publish(lc, NULL, resource, event, expires); } LinphoneEvent *linphone_proxy_config_create_publish(LinphoneProxyConfig *cfg, const char *event, int expires) { - + return _linphone_core_create_publish(NULL, cfg,NULL, event, expires); - - + + } LinphoneEvent *linphone_core_create_one_shot_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event){ LinphoneEvent *lev = linphone_core_create_publish(lc, resource, event, -1); @@ -439,20 +439,34 @@ const char *linphone_event_get_name(const LinphoneEvent *lev){ return lev->name; } -const LinphoneAddress *linphone_event_get_from(const LinphoneEvent *lev){ - if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing){ - return (LinphoneAddress*)sal_op_get_to_address(lev->op); - }else{ - return (LinphoneAddress*)sal_op_get_from_address(lev->op); - } +static const LinphoneAddress *_linphone_event_cache_to (const LinphoneEvent *lev) { + if (lev->to_address) + linphone_address_unref(lev->to_address); + char *buf = sal_address_as_string(sal_op_get_to_address(lev->op)); + ((LinphoneEvent *)lev)->to_address = linphone_address_new(buf); + ms_free(buf); + return lev->to_address; +} + +static const LinphoneAddress *_linphone_event_cache_from (const LinphoneEvent *lev) { + if (lev->from_address) + linphone_address_unref(lev->from_address); + char *buf = sal_address_as_string(sal_op_get_from_address(lev->op)); + ((LinphoneEvent *)lev)->from_address = linphone_address_new(buf); + ms_free(buf); + return lev->from_address; +} + +const LinphoneAddress *linphone_event_get_from (const LinphoneEvent *lev) { + if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing) + return _linphone_event_cache_to(lev); + return _linphone_event_cache_from(lev); } const LinphoneAddress *linphone_event_get_resource(const LinphoneEvent *lev){ - if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing){ - return (LinphoneAddress*)sal_op_get_from_address(lev->op); - }else{ - return (LinphoneAddress*)sal_op_get_to_address(lev->op); - } + if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing) + return _linphone_event_cache_from(lev); + return _linphone_event_cache_to(lev); } LinphoneCore *linphone_event_get_core(const LinphoneEvent *lev){ @@ -477,4 +491,3 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneEvent, belle_sip_object_t, _linphone_event_marshall, FALSE ); - diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 5c581889d..5acc89988 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -5018,7 +5018,10 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , void linphone_call_set_contact_op(LinphoneCall* call) { LinphoneAddress *contact; contact=get_fixed_contact(call->core,call,call->dest_proxy); - sal_op_set_and_clean_contact_address(call->op, (SalAddress *)contact); + sal_op_set_and_clean_contact_address( + call->op, + (SalAddress *)L_GET_PRIVATE_FROM_C_STRUCT(contact, Address)->getInternalAddress() + ); } LinphonePlayer *linphone_call_get_player(LinphoneCall *call){ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index c0f73ba71..aa964e191 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -46,6 +46,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "mediastreamer2/msogl.h" #include "mediastreamer2/msvolume.h" +// For migration purpose. +#include "address/address-p.h" +#include "c-wrapper/c-tools.h" + #ifdef INET6 #ifndef _WIN32 #include @@ -3383,7 +3387,7 @@ static bctbx_list_t *make_routes_for_proxy(LinphoneProxyConfig *proxy, const Lin ret=bctbx_list_append(ret,sal_address_new(local_route)); } if (srv_route){ - ret=bctbx_list_append(ret,sal_address_clone((SalAddress*)srv_route)); + ret=bctbx_list_append(ret,sal_address_clone(L_GET_PRIVATE_FROM_C_STRUCT(srv_route, Address)->getInternalAddress())); } if (ret==NULL){ /*if the proxy address matches the domain part of the destination, then use the same transport diff --git a/coreapi/presence.c b/coreapi/presence.c index a49550991..43c7a8ffd 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -1933,8 +1933,11 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa if (linphone_core_get_default_friend_list(lc) != NULL) lf=linphone_core_find_friend_by_out_subscribe(lc, op); if (lf==NULL && lp_config_get_int(lc->config,"sip","allow_out_of_subscribe_presence",0)){ - const SalAddress *addr=sal_op_get_from_address(op); - lf = linphone_core_find_friend(lc, (LinphoneAddress *)addr); + char *buf = sal_address_as_string_uri_only(sal_op_get_from_address(op)); + LinphoneAddress *addr = linphone_address_new(buf); + lf = linphone_core_find_friend(lc, addr); + ms_free(buf); + linphone_address_unref(addr); } if (lf!=NULL){ LinphonePresenceActivity *activity = NULL; diff --git a/coreapi/private.h b/coreapi/private.h index b6e2bd7f1..24f2b2649 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -1159,6 +1159,11 @@ struct _LinphoneEvent{ bool_t is_out_of_dialog_op; /*used for out of dialog notify*/ bool_t internal; bool_t oneshot; + + // For migration purpose. (Do not use directly!) + // Cache. + LinphoneAddress *to_address; + LinphoneAddress *from_address; }; BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneEvent); diff --git a/coreapi/proxy.c b/coreapi/proxy.c index ebfc42b54..9f71a609f 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -410,26 +410,39 @@ void linphone_proxy_config_apply(LinphoneProxyConfig *cfg,LinphoneCore *lc){ } void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig * cfg){ - LinphoneAddress *contact_addr=NULL; - if ( cfg->op - && cfg->state == LinphoneRegistrationOk - && (contact_addr = (LinphoneAddress*)sal_op_get_contact_address(cfg->op)) - && linphone_address_get_transport(contact_addr) != LinphoneTransportUdp /*with udp, there is a risk of port reuse, so I prefer to not do anything for now*/) { - /*need to save current contact in order to reset is later*/ - linphone_address_ref(contact_addr); - if (cfg->pending_contact) - linphone_address_unref(cfg->pending_contact); - cfg->pending_contact=contact_addr; - + LinphoneAddress *contact_addr = NULL; + { + const SalAddress *sal_addr = cfg->op && cfg->state == LinphoneRegistrationOk + ? sal_op_get_contact_address(cfg->op) + : NULL; + if (sal_addr) { + char *buf = sal_address_as_string(sal_addr); + contact_addr = buf ? linphone_address_new(buf) : NULL; + ms_free(buf); + } } - if (cfg->presence_publish_event){ /*might probably do better*/ + + /*with udp, there is a risk of port reuse, so I prefer to not do anything for now*/ + if (contact_addr) { + if (linphone_address_get_transport(contact_addr) != LinphoneTransportUdp) { + /*need to save current contact in order to reset is later*/ + linphone_address_ref(contact_addr); + if (cfg->pending_contact) + linphone_address_unref(cfg->pending_contact); + cfg->pending_contact=contact_addr; + } else + linphone_address_unref(contact_addr); + } + + if (cfg->presence_publish_event) { /*might probably do better*/ linphone_event_terminate(cfg->presence_publish_event); if (cfg->presence_publish_event) { - linphone_event_unref(cfg->presence_publish_event); /*probably useless as cfg->long_term_event is already unref in linphone_proxy_config_notify_publish_state_changed. To be check with Ghislain*/ - cfg->presence_publish_event=NULL; + /*probably useless as cfg->long_term_event is already unref in linphone_proxy_config_notify_publish_state_changed. To be check with Ghislain*/ + linphone_event_unref(cfg->presence_publish_event); + cfg->presence_publish_event = NULL; } - } + if (cfg->op){ sal_op_release(cfg->op); cfg->op=NULL; @@ -1394,9 +1407,11 @@ const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphonePro const char* linphone_proxy_config_get_transport(const LinphoneProxyConfig *cfg) { const char* addr=NULL; const char* ret="udp"; /*default value*/ - SalAddress* route_addr=NULL; + const SalAddress* route_addr=NULL; + bool_t destroy_route_addr = FALSE; + if (linphone_proxy_config_get_service_route(cfg)) { - route_addr=(SalAddress*)linphone_proxy_config_get_service_route(cfg); + route_addr = L_GET_PRIVATE_FROM_C_STRUCT(linphone_proxy_config_get_service_route(cfg), Address)->getInternalAddress(); } else if (linphone_proxy_config_get_route(cfg)) { addr=linphone_proxy_config_get_route(cfg); } else if(linphone_proxy_config_get_addr(cfg)) { @@ -1406,13 +1421,16 @@ const char* linphone_proxy_config_get_transport(const LinphoneProxyConfig *cfg) return NULL; } - if (route_addr || (route_addr=sal_address_new(addr))) { - ret=sal_transport_to_string(sal_address_get_transport(route_addr)); - if (!linphone_proxy_config_get_service_route(cfg)) { - sal_address_destroy(route_addr); - } + if (!route_addr) { + if (!((*(SalAddress **)&route_addr) = sal_address_new(addr))) + return NULL; + destroy_route_addr = TRUE; } + ret=sal_transport_to_string(sal_address_get_transport(route_addr)); + if (destroy_route_addr) + sal_address_destroy((SalAddress *)route_addr); + return ret; } void linphone_proxy_config_set_privacy(LinphoneProxyConfig *params, LinphonePrivacyMask privacy) { diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 9e8302dda..bee5dc6dc 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -32,6 +32,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #endif +// For migration purpose. +#include "address/address-p.h" +#include "c-wrapper/c-tools.h" + #define STR_REASSIGN(dest, src) {\ if (dest != NULL) \ ms_free(dest); \ @@ -272,6 +276,7 @@ static int send_report(LinphoneCall* call, reporting_session_report_t * report, LinphoneAddress *request_uri; const char* collector_uri; char *collector_uri_allocated = NULL; + const SalAddress *salAddress; /*if we are on a low bandwidth network, do not send reports to not overload it*/ if (linphone_call_params_low_bandwidth_enabled(linphone_call_get_current_params(call))){ @@ -362,8 +367,9 @@ static int send_report(LinphoneCall* call, reporting_session_report_t * report, * (port, transport, maddr), then it is sent directly. * Otherwise it is routed as any LinphoneEvent publish, following proxy config policy. **/ - if (sal_address_has_uri_param((SalAddress*)request_uri, "transport") || - sal_address_has_uri_param((SalAddress*)request_uri, "maddr") || + salAddress = L_GET_PRIVATE_FROM_C_STRUCT(request_uri, Address)->getInternalAddress(); + if (sal_address_has_uri_param(salAddress, "transport") || + sal_address_has_uri_param(salAddress, "maddr") || linphone_address_get_port(request_uri) != 0) { ms_message("Publishing report with custom route %s", collector_uri); sal_op_set_route(lev->op, collector_uri); diff --git a/src/address/address-p.h b/src/address/address-p.h index ed9005bf1..15364bfc1 100644 --- a/src/address/address-p.h +++ b/src/address/address-p.h @@ -36,12 +36,12 @@ public: private: struct AddressCache { - std::string scheme; - std::string displayName; - std::string username; - std::string domain; - std::string methodParam; - std::string password; + mutable std::string scheme; + mutable std::string displayName; + mutable std::string username; + mutable std::string domain; + mutable std::string methodParam; + mutable std::string password; mutable std::unordered_map headers; mutable std::unordered_map params; diff --git a/src/address/address.cpp b/src/address/address.cpp index b9d0965ba..ebb88f4ab 100644 --- a/src/address/address.cpp +++ b/src/address/address.cpp @@ -40,23 +40,13 @@ Address::Address (const string &address) : ClonableObject(*new AddressPrivate) { lWarning() << "Cannot create address, bad uri [" << address << "]."; return; } - - AddressPrivate::AddressCache &cache = d->cache; - cache.scheme = L_C_TO_STRING(sal_address_get_scheme(d->internalAddress)); - cache.displayName = L_C_TO_STRING(sal_address_get_display_name(d->internalAddress)); - cache.username = L_C_TO_STRING(sal_address_get_username(d->internalAddress)); - cache.domain = L_C_TO_STRING(sal_address_get_domain(d->internalAddress)); - cache.methodParam = L_C_TO_STRING(sal_address_get_method_param(d->internalAddress)); - cache.password = L_C_TO_STRING(sal_address_get_password(d->internalAddress)); } Address::Address (const Address &src) : ClonableObject(*new AddressPrivate) { L_D(Address); SalAddress *salAddress = src.getPrivate()->internalAddress; - if (salAddress) { + if (salAddress) d->internalAddress = sal_address_clone(salAddress); - d->cache = src.getPrivate()->cache; - } } Address::~Address () { @@ -72,7 +62,6 @@ Address &Address::operator= (const Address &src) { sal_address_destroy(d->internalAddress); SalAddress *salAddress = src.getPrivate()->internalAddress; d->internalAddress = salAddress ? sal_address_clone(salAddress) : nullptr; - d->cache = src.getPrivate()->cache; } return *this; @@ -89,11 +78,13 @@ bool Address::operator== (const Address &address) const { const string &Address::getScheme () const { L_D(const Address); + d->cache.scheme = L_C_TO_STRING(sal_address_get_scheme(d->internalAddress)); return d->cache.scheme; } const string &Address::getDisplayName () const { L_D(const Address); + d->cache.displayName = L_C_TO_STRING(sal_address_get_display_name(d->internalAddress)); return d->cache.displayName; } @@ -104,13 +95,12 @@ bool Address::setDisplayName (const string &displayName) { return false; sal_address_set_display_name(d->internalAddress, L_STRING_TO_C(displayName)); - d->cache.displayName = L_C_TO_STRING(sal_address_get_display_name(d->internalAddress)); - return true; } const string &Address::getUsername () const { L_D(const Address); + d->cache.username = L_C_TO_STRING(sal_address_get_username(d->internalAddress)); return d->cache.username; } @@ -121,13 +111,12 @@ bool Address::setUsername (const string &username) { return false; sal_address_set_username(d->internalAddress, L_STRING_TO_C(username)); - d->cache.username = L_C_TO_STRING(sal_address_get_username(d->internalAddress)); - return true; } const string &Address::getDomain () const { L_D(const Address); + d->cache.domain = L_C_TO_STRING(sal_address_get_domain(d->internalAddress)); return d->cache.domain; } @@ -138,8 +127,6 @@ bool Address::setDomain (const string &domain) { return false; sal_address_set_domain(d->internalAddress, L_STRING_TO_C(domain)); - d->cache.domain = L_C_TO_STRING(sal_address_get_domain(d->internalAddress)); - return true; } @@ -195,6 +182,7 @@ bool Address::isSip () const { const string &Address::getMethodParam () const { L_D(const Address); + d->cache.methodParam = L_C_TO_STRING(sal_address_get_method_param(d->internalAddress)); return d->cache.methodParam; } @@ -205,13 +193,12 @@ bool Address::setMethodParam (const string &methodParam) { return false; sal_address_set_method_param(d->internalAddress, L_STRING_TO_C(methodParam)); - d->cache.methodParam = L_C_TO_STRING(sal_address_get_method_param(d->internalAddress)); - return true; } const string &Address::getPassword () const { L_D(const Address); + d->cache.password = L_C_TO_STRING(sal_address_get_password(d->internalAddress)); return d->cache.password; } @@ -222,8 +209,6 @@ bool Address::setPassword (const string &password) { return false; sal_address_set_password(d->internalAddress, L_STRING_TO_C(password)); - d->cache.password = L_C_TO_STRING(sal_address_get_password(d->internalAddress)); - return true; } @@ -274,14 +259,10 @@ bool Address::weakEqual (const Address &address) const { const string &Address::getHeaderValue (const string &headerName) const { L_D(const Address); - try { - return d->cache.headers.at(headerName); - } catch (const exception &) { - const char *value = sal_address_get_header(d->internalAddress, L_STRING_TO_C(headerName)); - if (value) { - d->cache.headers[headerName] = value; - return d->cache.headers[headerName]; - } + const char *value = sal_address_get_header(d->internalAddress, L_STRING_TO_C(headerName)); + if (value) { + d->cache.headers[headerName] = value; + return d->cache.headers[headerName]; } return Utils::getEmptyConstRefObject(); @@ -294,27 +275,21 @@ bool Address::setHeader (const string &headerName, const string &headerValue) { return false; sal_address_set_header(d->internalAddress, L_STRING_TO_C(headerName), L_STRING_TO_C(headerValue)); - d->cache.headers[headerName] = L_C_TO_STRING(sal_address_get_header(d->internalAddress, L_STRING_TO_C(headerName))); - return true; } bool Address::hasParam (const string ¶mName) const { L_D(const Address); - return d->cache.params.find(paramName) != d->cache.params.cend(); + return sal_address_has_param(d->internalAddress, L_STRING_TO_C(paramName)); } const string &Address::getParamValue (const string ¶mName) const { L_D(const Address); - try { - return d->cache.params.at(paramName); - } catch (const exception &) { - const char *value = sal_address_get_param(d->internalAddress, L_STRING_TO_C(paramName)); - if (value) { - d->cache.params[paramName] = value; - return d->cache.params[paramName]; - } + const char *value = sal_address_get_param(d->internalAddress, L_STRING_TO_C(paramName)); + if (value) { + d->cache.params[paramName] = value; + return d->cache.params[paramName]; } return Utils::getEmptyConstRefObject(); @@ -327,32 +302,31 @@ bool Address::setParam (const string ¶mName, const string ¶mValue) { return false; sal_address_set_param(d->internalAddress, L_STRING_TO_C(paramName), L_STRING_TO_C(paramValue)); - d->cache.params[paramName] = L_C_TO_STRING(sal_address_get_param(d->internalAddress, L_STRING_TO_C(paramName))); - return true; } bool Address::setParams (const string ¶ms) { - // TODO. - return false; + L_D(Address); + + if (!d->internalAddress) + return false; + + sal_address_set_params(d->internalAddress, L_STRING_TO_C(params)); + return true; } bool Address::hasUriParam (const string &uriParamName) const { L_D(const Address); - return d->cache.uriParams.find(uriParamName) != d->cache.uriParams.cend(); + return sal_address_has_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName)); } const string &Address::getUriParamValue (const string &uriParamName) const { L_D(const Address); - try { - return d->cache.uriParams.at(uriParamName); - } catch (const exception &) { - const char *value = sal_address_get_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName)); - if (value) { - d->cache.uriParams[uriParamName] = value; - return d->cache.uriParams[uriParamName]; - } + const char *value = sal_address_get_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName)); + if (value) { + d->cache.uriParams[uriParamName] = value; + return d->cache.uriParams[uriParamName]; } return Utils::getEmptyConstRefObject(); @@ -365,14 +339,17 @@ bool Address::setUriParam (const string &uriParamName, const string &uriParamVal return false; sal_address_set_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName), L_STRING_TO_C(uriParamValue)); - d->cache.params[uriParamName] = L_C_TO_STRING(sal_address_get_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName))); - return true; } -bool Address::setUriParams (const string ¶ms) { - // TODO. - return false; +bool Address::setUriParams (const string &uriParams) { + L_D(Address); + + if (!d->internalAddress) + return false; + + sal_address_set_uri_params(d->internalAddress, L_STRING_TO_C(uriParams)); + return true; } LINPHONE_END_NAMESPACE diff --git a/src/address/address.h b/src/address/address.h index 10fdaadc9..84048a681 100644 --- a/src/address/address.h +++ b/src/address/address.h @@ -89,7 +89,7 @@ public: bool hasUriParam (const std::string &uriParamName) const; const std::string &getUriParamValue (const std::string &uriParamName) const; bool setUriParam (const std::string &uriParamName, const std::string &uriParamValue); - bool setUriParams (const std::string ¶ms); + bool setUriParams (const std::string &uriParams); private: L_DECLARE_PRIVATE(Address); diff --git a/src/c-wrapper/c-tools.h b/src/c-wrapper/c-tools.h index f5d1f7a61..9d8975fb8 100644 --- a/src/c-wrapper/c-tools.h +++ b/src/c-wrapper/c-tools.h @@ -52,6 +52,13 @@ public: return static_cast *>(object)->cppPtr; } + template + static inline std::shared_ptr getCppPtrFromC (const void *object) { + if (!object) + return std::shared_ptr(); + return static_cast *>(object)->cppPtr; + } + private: Wrapper ();