RInside Version 0.2.12
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
rinside_sample16.cpp
Go to the documentation of this file.
1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 //
3 // Simple example showing how expose a C++ function with custom data types
4 // This is a continuation of rinside_sample9.cpp
5 //
6 // Copyright (C) 2014 Christian Authmann
7 
8 #include <iostream>
9 
10 /*
11  * We have a simple data type with two values.
12  */
13 class Foo {
14  public:
15  Foo(int a, int b) : a(a), b(b) {
16  }
17  ~Foo() {
18  }
19 
20  // The compiler will add the default copy constructor, so this class is copyable.
21 
22  int a, b;
23 };
24 
25 
26 /*
27  * We define converters between Foo and R objects, see
28  * http://cran.r-project.org/web/packages/Rcpp/vignettes/Rcpp-extending.pdf
29  */
30 #include <RcppCommon.h>
31 /*
32  * These template declarations must be after RcppCommon.h and before Rcpp.h
33  * The implementation can follow later, when all of Rcpp/Rinside is available.
34  */
35 namespace Rcpp {
36  template<> SEXP wrap(const Foo &f);
37  template<> Foo as(SEXP sexp);
38 }
39 
40 #include <Rcpp.h>
41 #include <RInside.h>
42 
43 
44 /*
45  * After including Rcpp/Rinside, we can implement the converters.
46  */
47 template<> SEXP Rcpp::wrap(const Foo &f) {
48  Rcpp::List list;
49 
50  list["a"] = f.a;
51  list["b"] = f.b;
52 
53  // Like all internal Rcpp datatypes, the List can be autoconverted to a SEXP, so we can just return it.
54  // This is equivalent to: return Rcpp::wrap(list)
55  return list;
56 }
57 
58 template<> Foo Rcpp::as(SEXP sexp) {
59  Rcpp::List list = Rcpp::as<Rcpp::List>(sexp);
60  // Note: This does not work when compiled using clang with Rcpp 0.11.2 and older
61  return Foo(
62  list["a"],
63  list["b"]
64  );
65 }
66 
67 
68 // a c++ function we wish to expose to R
69 Foo swapFoo(Foo &input) {
70  Foo result(input.b, input.a);
71  return result;
72 }
73 
74 int main(int argc, char *argv[]) {
75 
76  // create an embedded R instance
77  RInside R(argc, argv);
78 
79  // expose the "swapFoo" function in the global environment
80  R["swapFoo"] = Rcpp::InternalFunction( &swapFoo );
81 
82  // create a foo instance and expose it
83  Foo f(0, 42);
84  R["foo"] = f;
85 
86  // call it, getting another Foo object
87  Foo result = R.parseEvalNT(
88  //"print(foo);" // a=0, b=42
89  "foo$a = 12;"
90  //"print(foo);" // a=12, b=42
91  "foo = swapFoo(foo);"
92  //"print(foo);" // a=42, b=12
93 
94  "foo;" // return the object
95  );
96 
97  std::cout << " Got result a=" << result.a << ", b=" << result.b << std::endl;
98  std::cout << " Expected a=42, b=12" << std::endl;
99 
100 }
Definition: foo.h:17
SEXP wrap(const Bar &bar)
Foo swapFoo(Foo &input)
Proxy parseEvalNT(const std::string &line)
Definition: RInside.cpp:388
int32_t a
Definition: foo.h:23
int32_t b
Definition: foo.h:23
int main(int argc, char *argv[])
Bar as(SEXP sexp)
Foo(int a, int b)