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 ;
}
|