Le 19 juin 2014 à 01:02, Tim Keitt <[email protected]> a écrit :
>
>
>
> On Wed, Jun 18, 2014 at 5:37 PM, Romain Francois <[email protected]>
> wrote:
> Le 19 juin 2014 à 00:30, Tim Keitt <[email protected]> a écrit :
>
>> On Wed, Jun 18, 2014 at 5:22 PM, Romain Francois <[email protected]>
>> wrote:
>> Le 19 juin 2014 à 00:15, Tim Keitt <[email protected]> a écrit :
>>
>>
>>>
>>> On Wed, Jun 18, 2014 at 5:07 PM, Romain Francois <[email protected]>
>>> wrote:
>>> Le 18 juin 2014 à 23:54, Tim Keitt <[email protected]> a écrit :
>>>
>>>
>>>> I'd like to raise a condition other than error or warning. Is that
>>>> possible using the Rcpp api? I assume this can be done via R internals,
>>>> but I'd prefer not to call error() directly (or is that the
>>>> recommendation?).
>>>>
>>>> THK
>>>
>>> Definitely not. Rf_error should really only be called from C code. If you
>>> call it from C++, there is a great chance you'll lose determinism as
>>> destructors for your c++ objects are very likely not to be called. Most of
>>> the time, it will just mean you'll never release some objects to the
>>> garbage collector, but it could also get you leaks or other nice stuff
>>> depending on what your destructors were supposed to do and did not get a
>>> chance to do.
>>>
>>> That was my understanding. Just wanted to be sure it was still the case.
>>>
>>>
>>> I'm not sure Rcpp has a way to raise an R condition apart from calling
>>> stop, which usually is good enough. Otherwise, you can borrow from Rcpp11
>>> and adapt some code from
>>> https://github.com/Rcpp11/Rcpp11/blob/450aade7338c16c34618ad0916003e8ca4fb58a6/inst/include/Rcpp/Condition.h
>>>
>>> Ah. I see. Eval "stop" in the global env with the condition as the
>>> argument. Clever.
>>
>> It is more of a hack due to lack of proper api from R.
>>
>> If you do this, make sure you don't have any c++ object in scope.
>> Essentially that means you would evaluate `stop( condition )` in a top level
>> catch block.
>>
>> Rcpp objects are I assume ok however.
>
> Depends what you mean by "ok". If you mean objects like NumericVector, ...
> their destructor is responsible for calling R_ReleaseObject, i.e. let go of
> the protection that was set by their constructor. If the destructor is not
> called because R error handling does a long jump, you will get objects
> forever protected.
>
> So things will seemingly work, until you exhaust the memory.
>
>> I will try "signalCondition" and see what happens.
>>
>> THK
>
>
> I can't get signalCondition to do anything.
What exactly did you try ? Did you catch the condition at the R level, with
withCallingHandlers or something. Just because you don't see something does not
mean nothing happens.
> This works although I've not tested it for leaks.
Easy enough to test for forgotten destructors.
#include <Rcpp.h>
using namespace Rcpp;
void raise_condition(const std::string& msg,
const std::string& type)
{
List cond;
cond["message"] = msg;
cond["call"] = R_NilValue;
cond.attr("class") = CharacterVector::create(type, "condition");
Function stopper("stop");
stopper(cond);
}
class A {
public:
A(){ Rprintf( "A::A()\n" ) ; }
~A(){ Rprintf( "A::~A()\n" ) ; }
} ;
// [[Rcpp::export]]
void test(){
A a ;
raise_condition( "foo", "bar") ;
}
/*** R
test()
*/
which gives me:
> test()
A::A()
Error: foo
So the destructor for A is never called. Not a big deal here, it was not doing
anything. But might be more problematic elsewhere.
> void raise_condition(const std::string& msg,
> const std::string& type)
> {
> List cond;
> cond["message"] = msg;
> cond["call"] = R_NilValue;
> cond.attr("class") = CharacterVector::create(type, "condition");
> Function stopper("stop");
> stopper(cond);
> }
>
> THK
>
> --
> http://www.keittlab.org/
_______________________________________________
Rcpp-devel mailing list
[email protected]
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel