diff --git a/DESCRIPTION b/DESCRIPTION index 7d05b95d6..f4e9f579a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: Rcpp Title: Seamless R and C++ Integration -Version: 1.0.6 -Date: 2021-01-14 +Version: 1.0.6.1 +Date: 2021-01-17 Author: Dirk Eddelbuettel, Romain Francois, JJ Allaire, Kevin Ushey, Qiang Kou, Nathan Russell, Douglas Bates and John Chambers Maintainer: Dirk Eddelbuettel diff --git a/inst/include/Rcpp/String.h b/inst/include/Rcpp/String.h index 5a1401ffa..f94c66d99 100644 --- a/inst/include/Rcpp/String.h +++ b/inst/include/Rcpp/String.h @@ -52,19 +52,19 @@ namespace Rcpp { typedef internal::const_string_proxy const_StringProxy; /** default constructor */ - String(): data(Rf_mkCharCE("", CE_UTF8)), buffer(), valid(true), buffer_ready(true), enc(CE_UTF8) { - Rcpp_PreserveObject(data); + String(): data(Rf_mkCharCE("", CE_UTF8)), token(R_NilValue), buffer(), valid(true), buffer_ready(true), enc(CE_UTF8) { + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String()"); } /** copy constructor */ - String(const String& other) : data(other.get_sexp()), valid(true), buffer_ready(false), enc(Rf_getCharCE(other.get_sexp())) { - Rcpp_PreserveObject(data); + String(const String& other) : data(other.get_sexp()), token(R_NilValue), valid(true), buffer_ready(false), enc(Rf_getCharCE(other.get_sexp())) { + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String(const String&)"); } /** construct a string from a single CHARSXP SEXP */ - String(SEXP charsxp) : data(R_NilValue) { + String(SEXP charsxp) : data(R_NilValue), token(R_NilValue) { if (TYPEOF(charsxp) == STRSXP) { data = STRING_ELT(charsxp, 0); } else if (TYPEOF(charsxp) == CHARSXP) { @@ -82,30 +82,30 @@ namespace Rcpp { valid = true; buffer_ready = false; enc = Rf_getCharCE(data); - Rcpp_PreserveObject(data); + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String(SEXP)"); } /** from string proxy */ - String(const StringProxy& proxy): data(proxy.get()), valid(true), buffer_ready(false), enc(Rf_getCharCE(proxy.get())) { - Rcpp_PreserveObject(data); + String(const StringProxy& proxy): data(proxy.get()), token(R_NilValue), valid(true), buffer_ready(false), enc(Rf_getCharCE(proxy.get())) { + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String(const StringProxy&)"); } - String(const StringProxy& proxy, cetype_t enc): data(proxy.get()), valid(true), buffer_ready(false) { - Rcpp_PreserveObject(data); + String(const StringProxy& proxy, cetype_t enc): data(proxy.get()), token(R_NilValue), valid(true), buffer_ready(false) { + token = Rcpp_PreserveObject(data); set_encoding(enc); RCPP_STRING_DEBUG("String(const StringProxy&, cetype_t)"); } /** from string proxy */ - String(const const_StringProxy& proxy): data(proxy.get()), valid(true), buffer_ready(false), enc(Rf_getCharCE(proxy.get())) { - Rcpp_PreserveObject(data); + String(const const_StringProxy& proxy): data(proxy.get()), token(R_NilValue), valid(true), buffer_ready(false), enc(Rf_getCharCE(proxy.get())) { + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String(const const_StringProxy&)"); } - String(const const_StringProxy& proxy, cetype_t enc): data(proxy.get()), valid(true), buffer_ready(false) { - Rcpp_PreserveObject(data); + String(const const_StringProxy& proxy, cetype_t enc): data(proxy.get()), token(R_NilValue), valid(true), buffer_ready(false) { + token = Rcpp_PreserveObject(data); set_encoding(enc); RCPP_STRING_DEBUG("String(const const_StringProxy&, cetype_t)"); } @@ -113,53 +113,142 @@ namespace Rcpp { /** from a std::string */ String(const std::string& s, cetype_t enc = CE_UTF8) : buffer(s), valid(false), buffer_ready(true), enc(enc) { data = R_NilValue; + token = R_NilValue; RCPP_STRING_DEBUG("String(const std::string&, cetype_t)"); } - String(const std::wstring& s, cetype_t enc = CE_UTF8) : data(internal::make_charsexp(s)), valid(true), buffer_ready(false), enc(enc) { - Rcpp_PreserveObject(data); + String(const std::wstring& s, cetype_t enc = CE_UTF8) : data(internal::make_charsexp(s)), token(R_NilValue), valid(true), buffer_ready(false), enc(enc) { + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String(const std::wstring&, cetype_t)"); } /** from a const char* */ String(const char* s, cetype_t enc = CE_UTF8) : buffer(s), valid(false), buffer_ready(true), enc(enc) { data = R_NilValue; + token = R_NilValue; RCPP_STRING_DEBUG("String(const char*, cetype_t)"); } - String(const wchar_t* s, cetype_t enc = CE_UTF8) : data(internal::make_charsexp(s)), valid(true), buffer_ready(false), enc(enc) { - Rcpp_PreserveObject(data); + String(const wchar_t* s, cetype_t enc = CE_UTF8) : data(internal::make_charsexp(s)), token(R_NilValue), valid(true), buffer_ready(false), enc(enc) { + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String(const wchar_t* s, cetype_t)"); } /** constructors from R primitives */ - String(int x) : data(internal::r_coerce(x)), valid(true), buffer_ready(false), enc(CE_UTF8) {Rcpp_PreserveObject(data);} - String(double x) : data(internal::r_coerce(x)), valid(true), buffer_ready(false), enc(CE_UTF8) {Rcpp_PreserveObject(data);} - String(bool x) : data(internal::r_coerce(x)), valid(true) , buffer_ready(false), enc(CE_UTF8) {Rcpp_PreserveObject(data);} - String(Rcomplex x) : data(internal::r_coerce(x)), valid(true), buffer_ready(false), enc(CE_UTF8) {Rcpp_PreserveObject(data);} - String(Rbyte x) : data(internal::r_coerce(x)), valid(true), buffer_ready(false), enc(CE_UTF8) {Rcpp_PreserveObject(data);} + String(int x) : data(internal::r_coerce(x)), token(R_NilValue), valid(true), buffer_ready(false), enc(CE_UTF8) { + token = Rcpp_PreserveObject(data); + } + String(double x) : data(internal::r_coerce(x)), token(R_NilValue), valid(true), buffer_ready(false), enc(CE_UTF8) { + token = Rcpp_PreserveObject(data); + } + String(bool x) : data(internal::r_coerce(x)), token(R_NilValue), valid(true) , buffer_ready(false), enc(CE_UTF8) { + token = Rcpp_PreserveObject(data); + } + String(Rcomplex x) : data(internal::r_coerce(x)), token(R_NilValue), valid(true), buffer_ready(false), enc(CE_UTF8) { + token = Rcpp_PreserveObject(data); + } + String(Rbyte x) : data(internal::r_coerce(x)), token(R_NilValue), valid(true), buffer_ready(false), enc(CE_UTF8) { + token = Rcpp_PreserveObject(data); + } ~String() { - Rcpp_ReleaseObject(data); + Rcpp_ReleaseObject(token); data = R_NilValue; + token = R_NilValue; } - inline String& operator=(int x ) { data = Rcpp_ReplaceObject(data, internal::r_coerce(x)); valid = true; buffer_ready = false; return *this; } - inline String& operator=(double x ) { data = Rcpp_ReplaceObject(data, internal::r_coerce(x)); valid = true; buffer_ready = false; return *this; } - inline String& operator=(Rbyte x ) { data = Rcpp_ReplaceObject(data, internal::r_coerce(x)); valid = true; buffer_ready = false; return *this; } - inline String& operator=(bool x ) { data = Rcpp_ReplaceObject(data, internal::r_coerce(x)); valid = true; buffer_ready = false; return *this; } - inline String& operator=(Rcomplex x) { data = Rcpp_ReplaceObject(data, internal::r_coerce(x)); valid = true; buffer_ready = false; return *this; } - inline String& operator=(SEXP x) { data = Rcpp_ReplaceObject(data, x); valid = true; buffer_ready = false; return *this; } - inline String& operator=(const StringProxy& proxy) { data = Rcpp_ReplaceObject(data, proxy.get()); valid = true; buffer_ready=false; return *this; } - inline String& operator=(const String& other) { data = Rcpp_ReplaceObject(data, other.get_sexp()); valid = true; buffer_ready = false; return *this; } - inline String& operator=(const std::string& s) { buffer = s; valid = false; buffer_ready = true; return *this; } - inline String& operator=(const char* s) { buffer = s; valid = false; buffer_ready = true; return *this; } + inline String& operator=(int x) { + data = internal::r_coerce(x); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(double x) { + data = internal::r_coerce(x); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(Rbyte x) { + data = internal::r_coerce(x); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(bool x) { + data = internal::r_coerce(x); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(Rcomplex x) { + data = internal::r_coerce(x); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(SEXP x) { + if (data != x) { + data = x; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + } + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(const StringProxy& proxy) { + SEXP x = proxy.get(); + if (data != x) { + data = x; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(x); + } + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(const String& other) { + SEXP x = other.get_sexp(); + if (data != x) { + data = x; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(x); + } + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(const std::string& s) { + buffer = s; + valid = false; + buffer_ready = true; + return *this; + } + inline String& operator=(const char* s) { + buffer = s; + valid = false; + buffer_ready = true; + return *this; + } private: template inline String& assign_wide_string(const T& s) { - data = Rcpp_ReplaceObject(data, internal::make_charsexp(s)); + data = internal::make_charsexp(s); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); valid = true; buffer_ready = false; return *this; @@ -191,7 +280,9 @@ namespace Rcpp { const char* buf = CHAR(data); std::wstring tmp(buf, buf + strlen(buf)); tmp += s; - data = Rcpp_ReplaceObject(data, internal::make_charsexp(tmp)); + data = internal::make_charsexp(tmp); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); valid = true; buffer_ready = false; return *this; @@ -205,7 +296,14 @@ namespace Rcpp { inline String& operator+=(const String& other) { RCPP_STRING_DEBUG("String::operator+=(const char*)"); if (is_na()) return *this; - if (other.is_na()) { data = Rcpp_ReplaceObject(data, NA_STRING); valid = true; buffer_ready = false; return *this; } + if (other.is_na()) { + data = NA_STRING; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } setBuffer(); buffer += other; valid = false; return *this; } @@ -213,7 +311,14 @@ namespace Rcpp { RCPP_STRING_DEBUG("String::operator+=(const StringProxy&)"); if (is_na()) return *this; SEXP proxy_sexp = proxy; - if (proxy_sexp == NA_STRING) { data = Rcpp_ReplaceObject(data, NA_STRING); valid = true; buffer_ready = false; return *this;} + if (proxy_sexp == NA_STRING) { + data = NA_STRING; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } setBuffer(); buffer += CHAR(proxy_sexp); valid = false; return *this; } @@ -221,14 +326,28 @@ namespace Rcpp { RCPP_STRING_DEBUG("String::operator+=(const StringProxy&)"); if (is_na()) return *this; SEXP proxy_sexp = proxy; - if (proxy_sexp == NA_STRING) { data = Rcpp_ReplaceObject(data, NA_STRING); valid = true; buffer_ready = false; return *this;} + if (proxy_sexp == NA_STRING) { + data = NA_STRING; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } setBuffer(); buffer += CHAR(proxy_sexp); valid = false; return *this; } inline String& operator+=(SEXP x) { RCPP_STRING_DEBUG("String::operator+=(SEXP)"); if (is_na()) return *this; - if (x == NA_STRING) { data = Rcpp_ReplaceObject(data, NA_STRING); valid = true; buffer_ready = false; return *this;} + if (x == NA_STRING) { + data = NA_STRING; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } setBuffer(); buffer += CHAR(x); valid = false; return *this; } @@ -359,8 +478,11 @@ namespace Rcpp { inline void set_na() { - data = Rcpp_ReplaceObject(data, NA_STRING); - valid = true; buffer_ready = false; + data = NA_STRING; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; } @@ -410,10 +532,12 @@ namespace Rcpp { if (valid) { // TODO: may longjmp on failure to translate? const char* translated = Rf_translateCharUTF8(data); - data = Rcpp_ReplaceObject(data, Rf_mkCharCE(translated, encoding)); + data = Rf_mkCharCE(translated, encoding); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); } else { data = get_sexp_impl(); - Rcpp_PreserveObject(data); + token = Rcpp_PreserveObject(data); valid = true; } } @@ -461,6 +585,7 @@ namespace Rcpp { /** the CHARSXP this String encapsulates */ SEXP data; + SEXP token; /** a buffer used to do string operations withough going back to the SEXP */ std::string buffer; @@ -485,7 +610,7 @@ namespace Rcpp { RCPP_STRING_DEBUG("setData"); if (!valid) { data = get_sexp_impl(); - Rcpp_PreserveObject(data); + token = Rcpp_PreserveObject(data); valid = true; } } diff --git a/inst/include/Rcpp/config.h b/inst/include/Rcpp/config.h index a074619af..aaa4ae277 100644 --- a/inst/include/Rcpp/config.h +++ b/inst/include/Rcpp/config.h @@ -30,7 +30,7 @@ #define RCPP_VERSION_STRING "1.0.6" // the current source snapshot -#define RCPP_DEV_VERSION RcppDevVersion(1,0,6,0) -#define RCPP_DEV_VERSION_STRING "1.0.6.0" +#define RCPP_DEV_VERSION RcppDevVersion(1,0,6,1) +#define RCPP_DEV_VERSION_STRING "1.0.6.1" #endif diff --git a/inst/include/Rcpp/routines.h b/inst/include/Rcpp/routines.h index 437e42aee..5d5763924 100644 --- a/inst/include/Rcpp/routines.h +++ b/inst/include/Rcpp/routines.h @@ -38,6 +38,11 @@ namespace Rcpp{ } double mktime00(struct tm &); struct tm * gmtime_(const time_t * const); + + void Rcpp_precious_init(); + void Rcpp_precious_teardown(); + SEXP Rcpp_precious_preserve(SEXP object); + void Rcpp_precious_remove(SEXP token); } SEXP rcpp_get_stack_trace(); @@ -127,6 +132,27 @@ namespace Rcpp { return fun(x); } + inline attribute_hidden void Rcpp_precious_init() { + typedef void (*Fun)(void); + static Fun fun = GET_CALLABLE("Rcpp_precious_init"); + fun(); + } + inline attribute_hidden void Rcpp_precious_teardown() { + typedef void (*Fun)(void); + static Fun fun = GET_CALLABLE("Rcpp_precious_teardown"); + fun(); + } + inline attribute_hidden SEXP Rcpp_precious_preserve(SEXP object) { + typedef SEXP (*Fun)(SEXP); + static Fun fun = GET_CALLABLE("Rcpp_precious_preserve"); + return fun(object); + } + inline attribute_hidden void Rcpp_precious_remove(SEXP token) { + typedef void (*Fun)(SEXP); + static Fun fun = GET_CALLABLE("Rcpp_precious_remove"); + fun(token); + } + } // The 'attribute_hidden' used here is a simple precessor defined from diff --git a/inst/include/Rcpp/storage/PreserveStorage.h b/inst/include/Rcpp/storage/PreserveStorage.h index be8d0fdab..7ed0f9aa4 100644 --- a/inst/include/Rcpp/storage/PreserveStorage.h +++ b/inst/include/Rcpp/storage/PreserveStorage.h @@ -7,15 +7,20 @@ namespace Rcpp{ class PreserveStorage { public: - PreserveStorage() : data(R_NilValue){} + PreserveStorage() : data(R_NilValue), token(R_NilValue){} ~PreserveStorage(){ - Rcpp_ReleaseObject(data) ; + Rcpp_ReleaseObject(token) ; data = R_NilValue; + token = R_NilValue; } inline void set__(SEXP x){ - data = Rcpp_ReplaceObject(data, x) ; + if (data != x) { + data = x; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + } // calls the update method of CLASS // this is where to react to changes in the underlying SEXP @@ -28,7 +33,9 @@ namespace Rcpp{ inline SEXP invalidate__(){ SEXP out = data ; + Rcpp_ReleaseObject(token); data = R_NilValue ; + token = R_NilValue ; return out ; } @@ -48,6 +55,7 @@ namespace Rcpp{ private: SEXP data ; + SEXP token ; } ; } diff --git a/inst/include/Rcpp/traits/named_object.h b/inst/include/Rcpp/traits/named_object.h index 761ac24de..17252fdd7 100644 --- a/inst/include/Rcpp/traits/named_object.h +++ b/inst/include/Rcpp/traits/named_object.h @@ -41,19 +41,22 @@ template class named_object { template <> class named_object { public: // #nocov start named_object( const std::string& name_, const SEXP& o_): - name(name_), object(o_) { - R_PreserveObject(object); + name(name_), object(o_), token(R_NilValue) { + token = Rcpp_precious_preserve(object); } named_object( const named_object& other ) : - name(other.name), object(other.object) { - R_PreserveObject(object); + name(other.name), object(other.object), token(other.token) { + token = Rcpp_precious_preserve(object); } ~named_object() { - R_ReleaseObject(object); + Rcpp_precious_remove(token); + } // #nocov end const std::string& name; SEXP object; +private: + SEXP token; }; diff --git a/inst/include/RcppCommon.h b/inst/include/RcppCommon.h index 41ecce70d..b42aba1aa 100644 --- a/inst/include/RcppCommon.h +++ b/inst/include/RcppCommon.h @@ -77,6 +77,9 @@ namespace Rcpp { SEXP Rcpp_fast_eval(SEXP expr_, SEXP env); SEXP Rcpp_eval(SEXP expr_, SEXP env = R_GlobalEnv); + SEXP Rcpp_precious_preserve(SEXP object); + void Rcpp_precious_remove(SEXP token); + namespace internal { SEXP Rcpp_eval_impl(SEXP expr, SEXP env); } @@ -87,28 +90,12 @@ namespace Rcpp { template class named_object; } - inline SEXP Rcpp_PreserveObject(SEXP x) { - if (x != R_NilValue) { - R_PreserveObject(x); - } - return x; - } - - inline void Rcpp_ReleaseObject(SEXP x) { - if (x != R_NilValue) { - R_ReleaseObject(x); - } + inline SEXP Rcpp_PreserveObject(SEXP object) { + return Rcpp_precious_preserve(object); } - inline SEXP Rcpp_ReplaceObject(SEXP x, SEXP y) { - - // if we are setting to the same SEXP as we already have, do nothing - if (x != y) { - Rcpp_ReleaseObject(x); - Rcpp_PreserveObject(y); - } - - return y; + inline void Rcpp_ReleaseObject(SEXP token) { + Rcpp_precious_remove(token); } } diff --git a/src/barrier.cpp b/src/barrier.cpp index 86b05e97e..bd0d115af 100644 --- a/src/barrier.cpp +++ b/src/barrier.cpp @@ -1,8 +1,6 @@ -// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 4 -*- -// // barrier.cpp: Rcpp R/C++ interface class library -- write barrier // -// Copyright (C) 2010 - 2019 Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2010 - 2020 Dirk Eddelbuettel and Romain Francois // // This file is part of Rcpp. // @@ -88,6 +86,46 @@ static SEXP Rcpp_cache = R_NilValue; #define RCPP_HASH_CACHE_INITIAL_SIZE 1024 #endif +namespace Rcpp { +static SEXP Rcpp_precious = R_NilValue; +// [[Rcpp::register]] +void Rcpp_precious_init() { + Rcpp_precious = CONS(R_NilValue, R_NilValue); // set up + R_PreserveObject(Rcpp_precious); // and protect +} +// [[Rcpp::register]] +void Rcpp_precious_teardown() { + R_ReleaseObject(Rcpp_precious); // release resource +} +// [[Rcpp::register]] +SEXP Rcpp_precious_preserve(SEXP object) { + if (object == R_NilValue) { + return R_NilValue; + } + PROTECT(object); + SEXP cell = PROTECT(CONS(Rcpp_precious, CDR(Rcpp_precious))); + SET_TAG(cell, object); + SETCDR(Rcpp_precious, cell); + if (CDR(cell) != R_NilValue) { + SETCAR(CDR(cell), cell); + } + UNPROTECT(2); + return cell; +} +// [[Rcpp::register]] +void Rcpp_precious_remove(SEXP token) { + if (token == R_NilValue) { + return; + } + SEXP before = CAR(token); + SEXP after = CDR(token); + SETCDR(before, after); + if (after != R_NilValue) { + SETCAR(after, before); + } +} +} + // only used for debugging SEXP get_rcpp_cache() { if (! Rcpp_cache_know) { diff --git a/src/rcpp_init.cpp b/src/rcpp_init.cpp index 4a6e00ccc..b8be84bf8 100644 --- a/src/rcpp_init.cpp +++ b/src/rcpp_init.cpp @@ -1,8 +1,6 @@ -// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- -// // Rcpp_init.cpp : Rcpp R/C++ interface class library -- Initialize and register // -// Copyright (C) 2010 - 2017 John Chambers, Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2010 - 2020 John Chambers, Dirk Eddelbuettel and Romain Francois // // This file is part of Rcpp. // @@ -121,22 +119,27 @@ void registerFunctions(){ RCPP_REGISTER(error_occured) RCPP_REGISTER(rcpp_get_current_error) // RCPP_REGISTER(print) + RCPP_REGISTER(Rcpp_precious_init) + RCPP_REGISTER(Rcpp_precious_teardown) + RCPP_REGISTER(Rcpp_precious_preserve) + RCPP_REGISTER(Rcpp_precious_remove) #undef RCPP_REGISTER } - -extern "C" void R_unload_Rcpp(DllInfo *) { // #nocov start - // Release resources -} // #nocov end +extern "C" void R_unload_Rcpp(DllInfo *) { // #nocov start + Rcpp::Rcpp_precious_teardown(); // release resource +} // #nocov end extern "C" void R_init_Rcpp(DllInfo* dllinfo) { setCurrentScope(0); - registerFunctions(); // call wrapper to register export symbols + registerFunctions(); // call wrapper to register export symbols + + R_useDynamicSymbols(dllinfo, FALSE); // set up symbol symbol lookup (cf R 3.4.0) - R_useDynamicSymbols(dllinfo, FALSE); // set up symbol symbol lookup (cf R 3.4.0) + init_Rcpp_cache(); // init the cache - init_Rcpp_cache(); // init the cache + Rcpp::Rcpp_precious_init(); - init_Rcpp_routines(dllinfo); // init routines + init_Rcpp_routines(dllinfo); // init routines }