Skip to content

Commit f960a6e

Browse files
committed
Merge branch 'master' into bugfix/newdatetimevec_ctor
2 parents 274c23f + 9af4818 commit f960a6e

File tree

8 files changed

+170
-26
lines changed

8 files changed

+170
-26
lines changed

ChangeLog

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@
44

55
* inst/include/Rcpp/date_datetime/newDatetimeVector.h (Rcpp): Small
66
correction concerning timezone attribute to ctor from RTYPE
7+
2016-11-22 Jim Hester <[email protected]>
8+
9+
* inst/src/api.cpp: Cleanup to stack message parseing
10+
* inst/unitTests/cpp/exceptions.cpp: Unit tests for cleanup
11+
* inst/unitTests/runit.exceptions.R: Ditto
12+
13+
2016-11-19 James J Balamuta <[email protected]>
14+
15+
* inst/unitTests/runit.environments.R: Added environment find unit tests
16+
as well as a symbol access test for environment get.
17+
* inst/unitTests/cpp/Environment.cpp: Idem
18+
19+
2016-11-18 James J Balamuta <[email protected]>
20+
* vignettes/Rcpp-extending: Switched to attributes and
21+
added external class pointer macro notes by MathurinD
722

823
2016-11-16 Dirk Eddelbuettel <[email protected]>
924

inst/NEWS.Rd

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,24 @@
33
\newcommand{\ghpr}{\href{https://github.com/RcppCore/Rcpp/pull/#1}{##1}}
44
\newcommand{\ghit}{\href{https://github.com/RcppCore/Rcpp/issues/#1}{##1}}
55

6+
\section{Changes in Rcpp version 0.12.9 (2017-01-xx)}{
7+
\item Changes in Rcpp API:
8+
\itemize{
9+
\item The exception stack message is now correctly demangled on all
10+
compiler versions (Jim Hester in \ghpr{598})
11+
}
12+
\item Changes in Rcpp unit tests
13+
\itemize{
14+
\item Added Environment::find unit tests and an Environment::get(Symbol)
15+
test (James Balamuta in \ghpr{595} addressing issue \ghit{594}).
16+
}
17+
\item Changes in Rcpp Documentation:
18+
\itemize{
19+
\item Exposed pointers macros were included in the Rcpp Extending vignette
20+
(MathurinD; James Balamuta in \ghpr{592} addressing \ghit{418}).
21+
}
22+
}
23+
624
\section{Changes in Rcpp version 0.12.8 (2016-11-16)}{
725
\itemize{
826
\item Changes in Rcpp API:

inst/unitTests/cpp/Environment.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@ SEXP runit_get( Environment env, std::string name){
3737
return env.get( name ) ;
3838
}
3939

40+
// [[Rcpp::export]]
41+
SEXP runit_get_symbol( Environment env, Symbol name){
42+
return env.get( name ) ;
43+
}
44+
45+
// [[Rcpp::export]]
46+
SEXP runit_find( Environment env, std::string name){
47+
return env.find( name ) ;
48+
}
49+
50+
// [[Rcpp::export]]
51+
SEXP runit_find_symbol( Environment env, Symbol name){
52+
return env.find( name ) ;
53+
}
54+
4055
// [[Rcpp::export]]
4156
bool runit_exists( Environment env, std::string st){
4257
return env.exists( st ) ;

inst/unitTests/cpp/exceptions.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ double takeLogRcpp(double val) {
3838
return log(val);
3939
}
4040

41+
// [[Rcpp::export]]
42+
double takeLogStop(double val) {
43+
if (val <= 0.0) {
44+
Rcpp::stop("Inadmissible value");
45+
}
46+
return log(val);
47+
}
48+
4149
// [[Rcpp::export]]
4250
double takeLogRcppLocation(double val) {
4351
if (val <= 0.0) {

inst/unitTests/runit.environments.R

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,44 @@ if (.runThisTest) {
4343
e <- new.env( )
4444
e$a <- 1:10
4545
e$b <- "foo"
46-
47-
checkEquals( runit_get( e, "a" ), e$a, msg = "Environment::get()" )
48-
checkEquals( runit_get( e, "foobar" ), NULL, msg = "Environment::get()" )
46+
47+
# Access with string
48+
checkEquals( runit_get( e, "a" ), e$a, msg = "Environment::get(string)" )
49+
checkEquals( runit_get( e, "foobar" ), NULL, msg = "Environment::get(string)" )
4950
checkEquals( runit_get( asNamespace("Rcpp"), "CxxFlags"), Rcpp:::CxxFlags,
50-
msg = "Environment(namespace)::get() " )
51-
52-
}
53-
51+
msg = "Environment(namespace)::get(string) " )
52+
53+
# Access with Symbol constructed on call from string
54+
checkEquals( runit_get_symbol( e, "a" ), e$a, msg = "Environment::get(Symbol)" )
55+
checkEquals( runit_get_symbol( e, "foobar" ), NULL, msg = "Environment::get(Symbol)" )
56+
checkEquals( runit_get_symbol( asNamespace("Rcpp"), "CxxFlags"), Rcpp:::CxxFlags,
57+
msg = "Environment(namespace)::get(Symbol) " )
58+
59+
}
60+
61+
test.environment.find <- function(){
62+
e <- new.env( )
63+
e$a <- 1:10
64+
e$b <- "foo"
65+
bar <- "me"
66+
67+
# Access with string
68+
checkEquals( runit_find( e, "a" ), e$a, msg = "Environment::find(string)" )
69+
checkException( runit_find( e, "foobar" ), NULL, msg = "Environment::find(string) not found" )
70+
checkEquals( runit_find( e, "bar"), bar, msg = "Environment::find(string) inheritance" )
71+
checkEquals( runit_find( asNamespace("Rcpp"), "CxxFlags"), Rcpp:::CxxFlags,
72+
msg = "Environment(namespace)::find(string)" )
73+
74+
# Access with Symbol constructed on call from string
75+
checkEquals( runit_find_symbol( e, "a" ), e$a, msg = "Environment::find(Symbol)" )
76+
checkException( runit_find_symbol( e, "foobar" ), NULL, msg = "Environment::find(Symbol) not found" )
77+
checkEquals( runit_find_symbol( e, "bar"), bar, msg = "Environment::find(Symbol) inheritance" )
78+
checkEquals( runit_find_symbol( asNamespace("Rcpp"), "CxxFlags"), Rcpp:::CxxFlags,
79+
msg = "Environment(namespace)::find(Symbol)" )
80+
81+
}
82+
83+
5484
test.environment.exists <- function(){
5585
e <- new.env( )
5686
e$a <- 1:10

inst/unitTests/runit.exceptions.R

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,24 @@ test.rcppException <- function() {
5858
checkEquals(condition$call, quote(takeLogRcpp(-1L)))
5959
}
6060

61+
test.rcppStop <- function() {
62+
63+
# Code works normally without an exception
64+
checkIdentical(takeLog(1L), log(1L))
65+
66+
# C++ exceptions are converted to R conditions
67+
condition <- tryCatch(takeLogStop(-1L), error = identity)
68+
69+
checkIdentical(condition$message, "Inadmissible value")
70+
checkIdentical(class(condition), c("Rcpp::exception", "C++Error", "error", "condition"))
71+
72+
checkTrue(!is.null(condition$cppstack))
73+
74+
checkIdentical(class(condition$cppstack), "Rcpp_stack_trace")
75+
76+
checkEquals(condition$call, quote(takeLogStop(-1L)))
77+
}
78+
6179
test.rcppExceptionLocation <- function() {
6280

6381
# Code works normally without an exception

src/api.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,24 @@ using namespace Rcpp;
3838
#else
3939
#include <execinfo.h>
4040

41+
// Extract mangled name e.g. ./test(baz+0x14)[0x400962]
4142
static std::string demangler_one(const char* input) {
4243
static std::string buffer;
4344
buffer = input;
44-
buffer.resize(buffer.find_last_of('+') - 1);
45-
buffer.erase(
46-
buffer.begin(),
47-
buffer.begin() + buffer.find_last_of(' ') + 1
48-
);
49-
return demangle(buffer);
45+
size_t last_open = buffer.find_last_of('(');
46+
size_t last_close = buffer.find_last_of(')');
47+
if (last_open == std::string::npos ||
48+
last_close == std::string::npos) {
49+
return input;
50+
}
51+
std::string function_name = buffer.substr(last_open + 1, last_close - last_open - 1);
52+
// Strip the +0x14 (if it exists, which it does not in earlier versions of gcc)
53+
size_t function_plus = function_name.find_last_of('+');
54+
if (function_plus != std::string::npos) {
55+
function_name.resize(function_plus);
56+
}
57+
buffer.replace(last_open + 1, function_name.size(), demangle(function_name));
58+
return buffer;
5059
}
5160
#endif
5261
#endif

vignettes/Rcpp-extending.Rnw

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,11 @@ These converters are often used implicitly, as in the following code chunk:
9191

9292
<<echo=FALSE>>=
9393
code <- '
94-
// we get a list from R
95-
List input(input_) ;
94+
#include <Rcpp.h>
95+
using namespace Rcpp;
96+
97+
// [[Rcpp::export]]
98+
List fx(List input){ // we get a list from R
9699
97100
// pull std::vector<double> from R list
98101
// this is achieved through an implicit call to Rcpp::as
@@ -103,7 +106,8 @@ std::vector<double> x = input["x"] ;
103106
return List::create(
104107
_["front"] = x.front(),
105108
_["back"] = x.back()
106-
) ;
109+
);
110+
}
107111
'
108112
writeLines( code, "code.cpp" )
109113
@
@@ -112,10 +116,7 @@ external_highlight( "code.cpp", type = "LATEX", doc = FALSE )
112116
@
113117

114118
<<>>=
115-
fx <- cxxfunction( signature( input_ = "list"),
116-
paste( readLines( "code.cpp" ), collapse = "\n" ),
117-
plugin = "Rcpp"
118-
)
119+
Rcpp::sourceCpp(file= "code.cpp")
119120
input <- list( x = seq(1, 10, by = 0.5) )
120121
fx( input )
121122
@
@@ -186,6 +187,18 @@ It should be noted that only the declaration is required. The implementation
186187
can appear after the \texttt{Rcpp.h} file is included, and therefore take
187188
full advantage of the \pkg{Rcpp} type system.
188189

190+
Another non-intrusive option is to expose an external pointer. The macro
191+
\texttt{RCPP\_EXPORT\_WRAP} provides an easy way to expose a \proglang{C++} class
192+
to \proglang{R} as an external pointer. It can be used instead of specializing
193+
\texttt{Rcpp::wrap}, and should not be used simultaneously.
194+
195+
<<lang=cpp>>=
196+
#include RcppCommon.h
197+
#include foobar.h
198+
199+
RCPP_EXPORT_WRAP(Bar);
200+
@
201+
189202
\subsection{Templates and partial specialization}
190203

191204
It is perfectly valid to declare a partial specialization for the
@@ -227,8 +240,6 @@ will attempt to use the constructor of the target class taking a \texttt{SEXP}.
227240
<<lang=cpp>>=
228241
#include <RcppCommon.h>
229242
230-
#include <RcppCommon.h>
231-
232243
class Foo{
233244
public:
234245
Foo() ;
@@ -237,18 +248,16 @@ class Foo{
237248
Foo(SEXP) ;
238249
}
239250
240-
#include <Rcpp.h>
241-
242251
243252
// this must appear after the specialization,
244253
// otherwise the specialization will not be seen by Rcpp types
245254
#include <Rcpp.h>
246255
@
247256

248-
\subsection{Non intrusive extension}
257+
\subsection{Non-intrusive extension}
249258

250259
It is also possible to fully specialize \texttt{Rcpp::as} to enable
251-
non intrusive implicit conversion capabilities.
260+
non-intrusive implicit conversion capabilities.
252261

253262
<<lang=cpp>>=
254263
#include <RcppCommon.h>
@@ -266,6 +275,28 @@ namespace Rcpp {
266275
#include <Rcpp.h>
267276
@
268277

278+
Furthermore, another non-intrusive option is to opt for sharing an R
279+
external pointer. The macro \texttt{RCPP\_EXPORT\_AS} provides an easy way to
280+
extend \texttt{Rcpp::as} to expose \proglang{R} external pointers to
281+
\proglang{C++}. It can be used instead of specializing \texttt{Rcpp::as}, and
282+
should not be used simultaneously.
283+
284+
<<lang=cpp>>=
285+
#include RcppCommon.h
286+
#include foobar.h
287+
288+
RCPP_EXPORT_AS(Bar);
289+
@
290+
291+
With this being said, there is one additional macro that can be used to
292+
simultaneously define both \texttt{Rcpp::wrap} and \texttt{Rcpp::as}
293+
specialization for an external pointer. The macro \texttt{RCPP\_EXPOSED\_CLASS}
294+
can be use to transparently exchange a class between \proglang{R} and
295+
\proglang{C++} as an external pointer. Do not simultaneously use it alongside
296+
\texttt{RCPP\_EXPOSED\_AS}, \texttt{RCPP\_EXPOSED\_WRAP}, \texttt{Rcpp::wrap}, or
297+
\texttt{Rcpp::as}.
298+
299+
269300
\subsection{Templates and partial specialization}
270301

271302
The signature of \texttt{Rcpp::as} does not allow partial specialization.

0 commit comments

Comments
 (0)