Revision: 474
http://rpy.svn.sourceforge.net/rpy/?rev=474&view=rev
Author: lgautier
Date: 2008-03-30 12:34:18 -0700 (Sun, 30 Mar 2008)
Log Message:
-----------
- arbitrary number of options
- evaluation of functions in their own closure
- putting back A. Belopolsky's "call Python from R" code
Modified Paths:
--------------
branches/rpy_nextgen/rpy/rinterface/rinterface.c
Modified: branches/rpy_nextgen/rpy/rinterface/rinterface.c
===================================================================
--- branches/rpy_nextgen/rpy/rinterface/rinterface.c 2008-03-30 07:29:46 UTC
(rev 473)
+++ branches/rpy_nextgen/rpy/rinterface/rinterface.c 2008-03-30 19:34:18 UTC
(rev 474)
@@ -31,8 +31,10 @@
*
* original RPy Authors: Walter Moreira.
* Gregory R. Warnes <[EMAIL PROTECTED]> (Maintainer)
- * Original code from wrapping R's C-level SEXPs: belopolsky
*
+ * Original code for wrapping R's C-level SEXPs: Alexander Belopolsky
+ * (this code borrows a *lot* from it)
+ *
* This code: Laurent Gautier
*
*
@@ -143,27 +145,22 @@
return NULL;
}
- //FIXME: arbitrary number of options
+ const Py_ssize_t n_args = PyTuple_Size(args);
//char *defaultargv[] = {"rpython", "--verbose"};
- char *options[5] = {"", "", "", "", ""};
-
- if (!PyArg_ParseTuple(args, "s|ssss",
- &options[0], &options[1],
- &options[2], &options[3],
- &options[4]
- )) {
- return NULL;
- }
-
- int n_opt;
- for (n_opt=0; n_opt<5; n_opt++) {
- if (options[n_opt] == "") {
- break;
+ char *options[n_args];
+ PyObject *opt_string;
+ Py_ssize_t ii;
+ for (ii = 0; ii < n_args; ii++) {
+ opt_string = PyTuple_GetItem(args, ii);
+ if (! PyString_Check(opt_string)) {
+ PyErr_SetString(PyExc_TypeError, "All options must be strings.");
+ return NULL;
}
+ options[ii] = PyString_AS_STRING(opt_string);
}
-
- int status = Rf_initEmbeddedR(n_opt, options);
+ int status = Rf_initEmbeddedR(n_args, options);
+
embeddedR_isInitialized = PyBool_FromLong((long)1);
globalEnv->sexp = R_GlobalEnv;
@@ -455,7 +452,7 @@
{
SEXP call_R, c_R, res_R;
int largs, lkwds;
- SEXP tmp_R;
+ SEXP tmp_R, fun_R;
largs = lkwds = 0;
if (args)
@@ -470,12 +467,12 @@
/* A SEXP with the function to call and the arguments and keywords. */
PROTECT(c_R = call_R = allocList(largs+lkwds+1));
SET_TYPEOF(c_R, LANGSXP);
- tmp_R = ((SexpObject *)self)->sexp;
- if (! tmp_R) {
+ fun_R = ((SexpObject *)self)->sexp;
+ if (! fun_R) {
PyErr_Format(PyExc_ValueError, "NULL SEXP.");
goto fail;
}
- SETCAR(c_R, tmp_R);
+ SETCAR(c_R, fun_R);
c_R = CDR(c_R);
int arg_i;
@@ -551,6 +548,7 @@
//FIXME: R_GlobalContext ?
PROTECT(res_R = do_eval_expr(call_R, R_GlobalEnv));
+ //PROTECT(res_R = do_eval_expr(call_R, CLOENV(fun_R)));
/* if (!res) { */
/* UNPROTECT(2); */
@@ -1394,8 +1392,106 @@
};
+/* A. Belopolsky's callback */
+/* R representation of a PyObject */
+static SEXP R_PyObject_type_tag;
+
+static SEXP
+R_PyObject_decref(SEXP s)
+{
+ PyObject* pyo = (PyObject*)R_ExternalPtrAddr(s);
+ if (pyo) {
+ Py_DECREF(pyo);
+ R_ClearExternalPtr(s);
+ }
+ return R_NilValue;
+}
+
+static SEXP
+mkPyObject(PyObject* pyo)
+{
+ SEXP res;
+ Py_INCREF(pyo);
+ res = R_MakeExternalPtr(pyo, R_PyObject_type_tag, R_NilValue);
+ R_RegisterCFinalizer(res, (R_CFinalizer_t)R_PyObject_decref);
+ return res;
+}
+
+#define R_PyObject_TYPE_CHECK(s) \
+ (TYPEOF(s) == EXTPTRSXP && R_ExternalPtrTag(s) == R_PyObject_type_tag)
+
+static SEXP
+do_Python(SEXP args)
+{
+ SEXP sexp = CADR(args);
+ SEXP res;
+ if (!R_PyObject_TYPE_CHECK(sexp)) {
+ error(".Python: invalid python type");
+ return R_NilValue;
+ }
+ //PyTypeObject* type = R_ExternalPtrAddr(sexp);
+ args = CDDR(args);
+ sexp = CAR(args);
+ if (!R_PyObject_TYPE_CHECK(sexp)) {
+ error(".Python: invalid function");
+ return R_NilValue;
+ }
+ PyObject *pyf = R_ExternalPtrAddr(sexp);
+
+ /* create argument list */
+ PyObject *pyargs = PyList_New(0);
+ PyObject *pyres;
+ for (args = CDR(args); args != R_NilValue; args = CDR(args)) {
+ sexp = CAR(args);
+ if (R_PyObject_TYPE_CHECK(sexp)) {
+ PyList_Append(pyargs, (PyObject *)R_ExternalPtrAddr(sexp));
+ }
+ else {
+ PyList_Append(pyargs, (PyObject *)newSexpObject(sexp));
+ }
+ }
+ PyObject *pyargstup = PyList_AsTuple(pyargs);
+ /*FIXME: named arguments are not supported yet */
+ pyres = PyObject_Call(pyf, pyargstup, NULL);
+ if (!pyres) {
+ PyObject *exctype;
+ PyObject *excvalue;
+ PyObject *exctraceback;
+ PyObject *excstr;
+ PyErr_Fetch(&exctype, &excvalue, &exctraceback);
+ excstr = PyObject_Str(excvalue);
+ if (excstr) {
+ error(PyString_AS_STRING(excstr));
+ Py_DECREF(excstr);
+ }
+ else {
+ error("Python error");
+ }
+ PyErr_Clear();
+ }
+ Py_DECREF(pyargs);
+ Py_DECREF(pyargstup);
+ if (PyObject_IsInstance((PyObject*)pyres,
+ (PyObject*)&Sexp_Type)) {
+ res = ((SexpObject*)pyres)->sexp;
+ }
+ else {
+ res = mkPyObject(pyres);
+ }
+ Py_DECREF(pyres);
+
+ return res;
+}
+
+static R_ExternalMethodDef externalMethods[] = {
+ {".Python", (DL_FUNC)&do_Python, -1},
+ {NULL, NULL, 0}
+};
+
+
+
/* --- Initialize the module ---*/
#define ADD_INT_CONSTANT(module, name) PyModule_AddIntConstant(module, #name,
name)
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
rpy-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rpy-list