File: internalfunction_clone.h

package info (click to toggle)
r-cran-rinside 0.2.14-1
  • links: PTS
  • area: main
  • in suites: buster
  • size: 608 kB
  • ctags: 617
  • sloc: cpp: 3,307; xml: 57; ansic: 41; makefile: 1
file content (82 lines) | stat: -rw-r--r-- 2,696 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
#pragma once

/*
 * Ok, frankly, this is a hack.
 * We need an InternalFunction, but we don't have a compatible C++ function - we only have
 * the parameter count and typeids.
 *
 * To do this, we need to get down to the point where the function parameters are nothing but an array of SEXP.
 * And that's so deep in the CppFunction implementation of Rcpp, that we need some detours to get there.
 */


class CppFunctionForRInsideServer: public Rcpp::CppFunctionBase {
	public:
		CppFunctionForRInsideServer(RInsideServer &server, uint32_t callback_id, const std::vector<int32_t> &types) : server(server), callback_id(callback_id), types(types) {
		}
		virtual ~CppFunctionForRInsideServer() {
		}
		SEXP operator()(SEXP* args) {
			// TODO: how do we get the amount of arguments passed? We should probably verify them.
			BEGIN_RCPP
			LOG("Callback %u called", callback_id);
			server.sendReply(RIS_REPLY_CALLBACK);
			server.stream.write(callback_id);
			size_t paramcount = types.size() - 1;
			for (size_t i=0;i<paramcount;i++) {
				LOG("Sending parameter %d at %p", (int) i, args[i]);
				server.allowSendReply();
				try {
					server.sexp_to_stream(args[i], types[i+1], true);
				}
				catch (const std::exception &e) {
					LOG("Exception sending argument: %s", e.what());
					throw;
				}
			}

			LOG("Reading result from stream");
			SEXP result = server.sexp_from_stream();
			server.allowSendReply();

			LOG("Got a SEXP, returning");
			// TODO: verify result type?
			return result;
			END_RCPP
		}
	private:
		RInsideServer &server;
		uint32_t callback_id;
		const std::vector<int32_t> types;
};

// Instantiate the standard deleter. TODO: can we avoid this?
template void Rcpp::standard_delete_finalizer(CppFunctionForRInsideServer* obj);


namespace Rcpp{

	// This is a clone of Rcpp's InternalFunction, just with a different constructor.
    RCPP_API_CLASS(InternalFunctionForRInsideServer_Impl) {
    public:

        RCPP_GENERATE_CTOR_ASSIGN(InternalFunctionForRInsideServer_Impl)

        InternalFunctionForRInsideServer_Impl(RInsideServer &server, uint32_t callback_id, const std::vector<int32_t> &types) {
			set(XPtr<CppFunctionForRInsideServer>(new CppFunctionForRInsideServer(server, callback_id, types), false));
		}

        void update(SEXP){}
    private:

        inline void set( SEXP xp){
            Environment RCPP = Environment::Rcpp_namespace() ;
            Function intf = RCPP["internal_function"] ;
            Storage::set__( intf( xp ) ) ;
        }

    };

    typedef InternalFunctionForRInsideServer_Impl<PreserveStorage> InternalFunctionForRInsideServer ;

}