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
rpy-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rpy-list

Reply via email to