def r_start(): global rlib if (rlib != None): return rlib os.environ["R_HOME"] = _get_rhome() rlib = _open_rlib() if (_main_loop_started()): return rlib import atexit atexit.register(r_end, 0) options = ("pins", "--quiet", "--vanilla", "--no-save") options_raw = [ffi.new("char[]", o.encode("ASCII")) for o in options] status = rlib.Rf_initialize_R(ffi.cast("int", len(options_raw)), options_raw) rlib.ptr_R_WriteConsoleEx = _console_write rlib.ptr_R_WriteConsole = ffi.NULL rlib.ptr_R_CleanUp = _cleanup rlib.ptr_R_ProcessEvents = _processevents rlib.ptr_R_Busy = _busy rlib.setup_Rmainloop() return rlib
def r_eval(code, environment=None): r_start() cmdSexp = rlib.Rf_allocVector(rlib.STRSXP, 1) rlib.Rf_protect(cmdSexp) ffi_code = ffi.new("char[]", code.encode("ASCII")) rlib.SET_STRING_ELT(cmdSexp, 0, rlib.Rf_mkChar(ffi_code)) status = ffi.new("ParseStatus *") cmdexpr = rlib.Rf_protect( rlib.R_ParseVector(cmdSexp, -1, status, rlib.R_NilValue)) rlib.Rf_unprotect(2) if status[0] != rlib.PARSE_OK: raise RuntimeError("Failed to parse: " + code) if environment == None: environment = rlib.R_GlobalEnv error = ffi.new("int *") result = rlib.Rf_protect( rlib.R_tryEval(rlib.VECTOR_ELT(cmdexpr, 0), environment, error)) if (error[0]): message = r_eval("gsub('\\\n', '', geterrmessage())") raise RuntimeError(message + " at " + code) rtype = result.sxpinfo.type if (rtype == rlib.CHARSXP): result = ffi.string(rlib.R_CHAR(result)).decode("utf-8") elif (rtype == rlib.STRSXP): result = ffi.string(rlib.R_CHAR(rlib.STRING_ELT(result, 0))).decode("utf-8") elif (rtype == rlib.RAWSXP): n = rlib.Rf_xlength(result) result = ffi.buffer(rlib.RAW(result), n) rlib.Rf_unprotect(1) return result