def rcall(self, keyvals, environment: typing.Optional[SexpEnvironment] = None): """Call/evaluate an R function. Args: - keyvals: a sequence of key/value (name/parameter) pairs. A name/parameter that is None will indicated an unnamed parameter. Like in R, keys/names do not have to be unique, partial matching can be used, and named/unnamed parameters can occur at any position in the sequence. - environment: an optional R environment to evaluate the function. """ # TODO: check keyvals are pairs ? if environment is None: environment = _evaluation_context assert isinstance(environment, SexpEnvironment) error_occured = _rinterface.ffi.new('int *', 0) with memorymanagement.rmemory() as rmemory: call_r = rmemory.protect( _rinterface.build_rcall(self.__sexp__._cdata, [], keyvals)) res = rmemory.protect( openrlib.rlib.R_tryEval(call_r, environment.__sexp__._cdata, error_occured)) if error_occured[0]: raise embedded.RRuntimeError(_rinterface._geterrmessage()) return res
def findvar_in_frame(rho, symbol): """Safer wrapper around Rf_findVarInFrame() Run the function Rf_findVarInFrame() in R's C-API through R_ToplevelExec(). Note: All arguments, and the object returned, are C-level R objects. Args: - rho: An R environment. - symbol: An R symbol (as returned by Rf_install()) Returns: The object found. """ # One would expect this to be like # res = _rinterface._findfun(symbol, self.__sexp__._cdata) # but R's findfun will segfault if an error occurs while # accessing the matching object in the environment. exec_data = ffi.new('struct RPY2_sym_env_data *', [symbol, rho, openrlib.rlib.R_NilValue]) _ = openrlib.rlib.R_ToplevelExec(openrlib.rlib._exec_findvar_in_frame, exec_data) if _ != openrlib.rlib.TRUE: raise embedded.RRuntimeError('R C-API Rf_findVarInFrame()') return exec_data.data
def __call__(self, *args, **kwargs) -> Sexp: error_occured = _rinterface.ffi.new('int *', 0) with memorymanagement.rmemory() as rmemory: call_r = rmemory.protect( _rinterface.build_rcall(self.__sexp__._cdata, args, kwargs.items())) res = rmemory.protect( openrlib.rlib.R_tryEval(call_r, globalenv.__sexp__._cdata, error_occured)) if error_occured[0]: raise embedded.RRuntimeError(_rinterface._geterrmessage()) return res
def rcall(self, keyvals, environment: SexpEnvironment): # TODO: check keyvals are pairs ? assert isinstance(environment, SexpEnvironment) error_occured = _rinterface.ffi.new('int *', 0) with memorymanagement.rmemory() as rmemory: call_r = rmemory.protect( _rinterface.build_rcall(self.__sexp__._cdata, [], keyvals)) res = rmemory.protect( openrlib.rlib.R_tryEval(call_r, environment.__sexp__._cdata, error_occured)) if error_occured[0]: raise embedded.RRuntimeError(_rinterface._geterrmessage()) return res
def unserialize(cdata: FFI.CData, cdata_env: FFI.CData) -> FFI.CData: """Unserialize an R string to an R object. Note that the R object returned is *not* protected from the R garbage collection.""" rlib = openrlib.rlib with memorymanagement.rmemory() as rmemory: sym_unserialize = rmemory.protect( rlib.Rf_install(conversion._str_to_cchar('unserialize'))) func_unserialize = rmemory.protect( _findfun(sym_unserialize, rlib.R_BaseEnv)) r_call = rmemory.protect(rlib.Rf_lang2(func_unserialize, cdata)) error_occured = ffi.new('int *', 0) res = rlib.R_tryEval(r_call, cdata_env, error_occured) if error_occured[0]: raise embedded.RRuntimeError(_geterrmessage()) return res