File: rinside_sample16.cpp

package info (click to toggle)
r-cran-rinside 0.2.19-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 668 kB
  • sloc: cpp: 3,310; ansic: 117; xml: 57; ruby: 34; makefile: 2
file content (100 lines) | stat: -rw-r--r-- 2,560 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
//
// Simple example showing how expose a C++ function with custom data types
// This is a continuation of rinside_sample9.cpp
//
// Copyright (C) 2014 Christian Authmann

#include <iostream>

/*
 * We have a simple data type with two values.
 */
class Foo {
    public:
        Foo(int a, int b) : a(a), b(b) {
        }
        ~Foo() {
        }

        // The compiler will add the default copy constructor, so this class is copyable.

        int a, b;
};


/*
 * We define converters between Foo and R objects, see
 * http://cran.r-project.org/web/packages/Rcpp/vignettes/Rcpp-extending.pdf
 */
#include <RcppCommon.h>
/*
 * These template declarations must be after RcppCommon.h and before Rcpp.h
 * The implementation can follow later, when all of Rcpp/Rinside is available.
 */
namespace Rcpp {
    template<> SEXP wrap(const Foo &f);
    template<> Foo as(SEXP sexp);
}

#include <Rcpp.h>
#include <RInside.h>


/*
 * After including Rcpp/Rinside, we can implement the converters.
 */
template<> SEXP Rcpp::wrap(const Foo &f) {
    Rcpp::List list;

    list["a"] = f.a;
    list["b"] = f.b;

    // Like all internal Rcpp datatypes, the List can be autoconverted to a SEXP, so we can just return it.
    // This is equivalent to: return Rcpp::wrap(list)
    return list;
}

template<> Foo Rcpp::as(SEXP sexp) {
    Rcpp::List list = Rcpp::as<Rcpp::List>(sexp);
    // Note: This does not work when compiled using clang with Rcpp 0.11.2 and older
    return Foo(
        list["a"],
        list["b"]
    );
}


// a c++ function we wish to expose to R
Foo swapFoo(Foo &input) {
    Foo result(input.b, input.a);
    return result;
}

int main(int argc, char *argv[]) {

    // create an embedded R instance
    RInside R(argc, argv);

    // expose the "swapFoo" function in the global environment
    R["swapFoo"] = Rcpp::InternalFunction( &swapFoo );

    // create a foo instance and expose it
    Foo f(0, 42);
    R["foo"] = f;

    // call it, getting another Foo object
    Foo result = R.parseEvalNT(
        //"print(foo);" // a=0, b=42
        "foo$a = 12;"
        //"print(foo);" // a=12, b=42
        "foo = swapFoo(foo);"
        //"print(foo);" // a=42, b=12

        "foo;" // return the object
    );

    std::cout << "    Got result a=" << result.a << ", b=" << result.b << std::endl;
    std::cout << "    Expected   a=42, b=12" << std::endl;

}