2014-10-06 1 views
1

Rcpp를 사용하여 C++ 스크립트에 대한 R 바인딩을 쓰려고합니다. 함수 중 하나는 std::shared_ptr object입니다. std::shared_ptr obj를 초기화하고 R 측에 Rcpp::XPtr 객체로 반환하는 것은 어렵습니다.std :: shared_ptr 개체 만들기 및 R쪽으로 반환 (Rcpp)

#include <iostream> 
#include <memory> 
#include <Rcpp.h> 
using namespace Rcpp; 
using std::cout; 


class TestClass { 
    public: 
    int value; 

    TestClass(int initial_val) { 
     value = initial_val; 
    }; 

}; 


//[[Rcpp::export]] 
SEXP get_test_obj() { 
    Rcpp::XPtr<std::shared_ptr<TestClass>> ptr(std::make_shared<TestClass>(5), true); 
    return ptr; 
}; 

그러나 다음과 같은 오류 얻을 :

나는 (최소한의 예) 해봤이 작업을 수행하는 방법에 대한

no matching function for call to 'Rcpp::XPtr<std::shared_ptr<TestClass> >::XPtr(std::shared_ptr<TestClass>, bool)' 

어떤 아이디어? 아니면 내가 잘못 생각할 것인가?

+1

'Rcpp :: XPtr'를 사용하여 몇 가지 프로젝트가 있습니다, 그들이하는 일을 더 자세히 보면서 여기서 당신을 도울 수 있습니까? –

+1

그리고 [Rcpp :: XPtr'을 보여주는 다른 질문들이 많이 있습니다.] (http://stackoverflow.com/search?q=%5Brcpp%5D+XPtr). –

답변

5

R 측에서 std :: shared_ptr을 전달할 것으로 예상됩니다. 나는 당신의 소스에있는 다른 코드가 std :: shared_ptr에 의존한다고 가정하고 있지만 R에 내부 원시 포인터를 전달하려고합니다. std :: shared_ptr의 수명이 코드에서보다 적절히 관리되고 있다고 가정합니다. 제시된 코드는 std :: shared_ptr이 함수 다음에 범위를 벗어나서 다음 역 참조시에 충돌하게 만들 것이기 ​​때문이다. 당신은 단지 R에 내부 원시 포인터를 전달하기를 원한다면 어떤 경우

, 당신은 (인위적인)과 같이 그것을 할 것 :

//[[Rcpp::export]] 
SEXP get_test_obj() { 
    std::shared_ptr<TestClass> s_ptr = std::make_shared<TestClass>(5); 
    Rcpp::XPtr<TestClass> x_ptr(s_ptr.get(), true); 
    return x_ptr; 
}; 
+1

컴파일러에서 'shared_ptr'이 'std'의 멤버가 아닙니다. 아직 작동합니까? –

5

대답을 @ d3coy에서 거의 모든 정보를 가지고 . Rcpp::XPtr은 템플릿 스마트 포인터 클래스이며 매개 변수는 가리키는 클래스가 아니라 pointee 클래스입니다. 따라서 Rcpp::XPtr<std::shared_ptr<TestClass>>std::shared_ptr<TestClass>*에 대한 스마트 포인터입니다. *에 주목하십시오. 중요한 비트입니다.

shared_ptr이 범위를 벗어나면 원시 포인터의 마지막 소유자 인 경우 원시 포인터가 삭제 될 수 있습니다. 그건 네가 원하는 것이 아니다.

new으로 원시 포인터를 만들 수 있으며 그걸로 XPtr을 제공 할 수 있습니다. 이 포인터는 가비지 콜렉터가 XPtr의 R 객체를 수집 할 때 delete d가됩니다. 이것은 외부 포인터를 처리 할 때 일반적으로 원하는 것입니다.

현재 지침은 new 대신 가능한 한 많이 make_uniquemake_shared을 사용하는 것이지만이 경우에는 new이 필요합니다. 똑똑함은 XPtr에서 나온 것이며 shared_ptr과 섞으면 서로 방해가 될 것입니다.

2

모든 도움말과 '포인터'를 보내 주셔서 감사합니다. 이것이 올바른 대응 방법인지 확신 할 수는 없지만 내가 찾은 해결책을 입력 할 수 있다고 생각했습니다.

요점은 R면이 참으로 std::shared_ptr을 필요로하지 않는다는 것입니다. 그러나 기존 C++ 라이브러리와 인터페이스하고 있습니다. 라이브러리 std::shared_ptr<TestClass> (R 사용)을 인스턴스화하고 std::shared_ptr<TestClass>을 예상하는 C++ 알고리즘에 다시 피드해야합니다.

#include <iostream> 
#include <memory> 
#include <Rcpp.h> 
using namespace Rcpp; 
using std::cout; 


class TestClass { 
    public: 
    int value; 
    TestClass(int initial_val): value(initial_val) {} 

}; 

class TestClassContainer { 
    public 
    std::shared_ptr<TestClass> test_class_obj; 
    TestClassContainer(): test_class_obj(std::make_shared<TestClass>()) {} 
}; 

//[[Rcpp::export]] 
SEXP get_test_obj() { 
    Rcpp::XPtr<TestClassContainer> ptr(new TestClassContainer(), true); 
    return ptr; 
}; 

//[[Rcpp::export]] 
SEXP do_something_with_shared_ptr_testclass(SEXP test_container_obj) { 
    Rcpp::XPtr<ResourceContainer> test_ptr(test_container_obj); 
    ExternalLib::do_function(test_container_obj->test_class_obj); 
}; 

그런 다음 RI에서 수행 할 수 있습니다 :

방법 내가 그것을 다음과 같이 (예 및 검증되지 않은)입니다 해결

test_container <- get_test_obj() 
do_something_with_shared_ptr_testclass(test_container) 
관련 문제