def _register_external_symbols() -> None: python_cchar = ffi.new('char []', b'.Python') externalmethods = ffi.new( 'R_ExternalMethodDef[]', [[python_cchar, ffi.cast('DL_FUNC', _evaluate_in_r), -1], [ffi.NULL, ffi.NULL, 0]]) openrlib.rlib.R_registerRoutines(openrlib.rlib.R_getEmbeddingDllInfo(), ffi.NULL, ffi.NULL, ffi.NULL, externalmethods)
def unserialize(cdata, cdata_env): """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
def _initr_win32(interactive: bool = True) -> int: embedded.rstart = ffi.new('Rstart') rstart = embedded.rstart rstart.rhome = openrlib.rlib.get_R_HOME() rstart.home = openrlib.rlib.getRUser() rstart.CharacterMode = openrlib.rlib.LinkDLL rstart.ReadConsole = callbacks._consoleread rstart.WriteConsole = callbacks._consolewrite_ex rstart.CallBack = callbacks._callback rstart.ShowMessage = callbacks._showmessage rstart.YesNoCancel = callbacks._yesnocancel rstart.Busy = callbacks._busy rstart.R_Quiet = True rstart.R_Interactive = interactive rstart.RestoreAction = openrlib.rlib.SA_RESTORE rstart.SaveAction = openrlib.rlib.SA_NOSAVE embedded.setinitialized() # TODO: still needed ? openrlib.rlib.R_CStackLimit = ffi.cast('uintptr_t', -1) openrlib.rlib.setup_Rmainloop() return 1
def _initr(interactive: bool = True) -> int: rlib = openrlib.rlib with openrlib.rlock: if isinitialized(): return os.environ['R_HOME'] = openrlib.R_HOME options_c = [ffi.new('char[]', o.encode('ASCII')) for o in _options] n_options = len(options_c) status = rlib.Rf_initialize_R(ffi.cast('int', n_options), options_c) global rstart rstart = ffi.new('Rstart') rstart.R_Interactive = interactive # TODO: Conditional definition in C code # (Aqua, TERM, and TERM not "dumb") rlib.R_Outputfile = ffi.NULL rlib.R_Consolefile = ffi.NULL rlib.ptr_R_WriteConsoleEx = callbacks._consolewrite_ex rlib.ptr_R_WriteConsole = ffi.NULL # TODO: Conditional in C code rlib.R_SignalHandlers = 0 rlib.ptr_R_ShowMessage = callbacks._showmessage rlib.ptr_R_ReadConsole = callbacks._consoleread rlib.ptr_R_FlushConsole = callbacks._consoleflush rlib.ptr_R_ResetConsole = callbacks._consolereset rlib.ptr_R_ChooseFile = callbacks._choosefile rlib.ptr_R_ShowFiles = callbacks._showfiles rlib.ptr_R_CleanUp = callbacks._cleanup rlib.ptr_R_ProcessEvents = callbacks._processevents rlib.ptr_R_Busy = callbacks._busy setinitialized() # TODO: still needed ? rlib.R_CStackLimit = ffi.cast('uintptr_t', -1) rlib.setup_Rmainloop() return status
def _parse(cdata, num): rlib = openrlib.rlib status = ffi.new('ParseStatus[1]', None) res = rlib.Rf_protect( rlib.R_ParseVector( cdata, # text num, status, rlib.R_NilValue)) # TODO: design better handling of possible status: # PARSE_NULL, # PARSE_OK, # PARSE_INCOMPLETE, # PARSE_ERROR, # PARSE_EOF if status[0] != rlib.PARSE_OK: rlib.Rf_unprotect(1) raise RParsingError('R parsing', PARSING_STATUS(status[0])) rlib.Rf_unprotect(1) return res
def _str_to_cchar(s, encoding: str = 'utf-8'): # TODO: use isStrinb and installTrChar b = s.encode(encoding) return ffi.new('char[]', b)