Revision: 404
http://rpy.svn.sourceforge.net/rpy/?rev=404&view=rev
Author: lgautier
Date: 2008-02-23 07:24:21 -0800 (Sat, 23 Feb 2008)
Log Message:
-----------
Initial commit on sourceforge.
Status is: kinda-almost-pre-alpha
Added Paths:
-----------
trunk/sandbox/rpy_nextgen/
trunk/sandbox/rpy_nextgen/rinterface/
trunk/sandbox/rpy_nextgen/rinterface/rinterface.c
trunk/sandbox/rpy_nextgen/setup.py
Added: trunk/sandbox/rpy_nextgen/rinterface/rinterface.c
===================================================================
--- trunk/sandbox/rpy_nextgen/rinterface/rinterface.c
(rev 0)
+++ trunk/sandbox/rpy_nextgen/rinterface/rinterface.c 2008-02-23 15:24:21 UTC
(rev 404)
@@ -0,0 +1,976 @@
+/* A python-R interface*/
+
+/*
+ * This is an attempt at cleaning up RPy, while adding features
+ * at the same time. In other words, this can be seen as a rewrite
+ * of RPy.
+ *
+ * The authors for the original RPy code, as well as
+ * belopolsky's contributed code, are listed here as authors;
+ * parts of this code is (sometimes shamelessly but with great
+ * respect for the work) "inspired" from their contributions.
+ *
+ * FIXME: get everyone's name in the license block
+ *
+ * Laurent Gautier - 2008
+ */
+
+/*
+ ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "Python.h"
+
+#include <R.h>
+#include <Rinternals.h>
+#include <Rdefines.h>
+#include <Rinterface.h>
+#include <Rembedded.h>
+
+/* FIXME: consider the use of parsing */
+/* #include <R_ext/Parse.h> */
+#include <R_ext/Rdynload.h>
+
+#include <signal.h>
+
+//FIXME: get this out ASAP
+#define VERBOSE
+
+//FIXME: see the details of error handling
+static PyObject *ErrorObject;
+
+//FIXME: see the details of interruption
+/* Indicates whether the R interpreter was interrupted by a SIGINT */
+int interrupted = 0;
+/* Abort the current R computation due to a SIGINT */
+static void
+interrupt_R(int signum)
+{
+ interrupted = 1;
+ error("Interrupted");
+}
+
+
+
+
+/* The Python original SIGINT handler */
+PyOS_sighandler_t python_sigint;
+
+PyDoc_STRVAR(module_doc,
+ "Low-level functions to interface with R.\n\
+ One should mostly consider calling the functions defined here when\
+ writing a higher level interface between python and R.\
+ Check the documentation for the module this is bundled into if\
+ you only wish to have an off-the-shelf interface with R.\
+\n\
+ Example of usage:\
+import rinterface\
+rinterface.initEmbeddedR(\"foo\", \"--verbose\")\
+n = rinterface.SexpVector(rinterface.REALSXP, (100,))\
+hist = rinterface.findVarEmbeddedR(\"hist\")\
+rnorm = rinterface.findVarEmbeddedR(\"rnorm\")\
+x = rnorm(n)\
+hist(x)\
+");
+//FIXME: check example above
+
+
+/* Representation of R objects (instances) as instances in Python.
+ */
+typedef struct {
+ PyObject_HEAD
+ SEXP sexp;
+} SexpObject;
+
+
+
+
+/* --- Initialize and terminate an embedded R --- */
+/* Should having multiple threads of R become possible,
+ * Useful routines deal with can could appear here...
+ */
+static PyObject* EmbeddedR_init(PyObject *self, PyObject *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;
+ }
+ }
+
+ int status = Rf_initEmbeddedR(n_opt, options);
+ PyObject *res = PyInt_FromLong(status);
+ return res;
+}
+PyDoc_STRVAR(EmbeddedR_init_doc,
+ "initEmbeddedR()\n\
+\n\
+Initialize an embedded R.");
+
+
+static PyObject* EmbeddedR_end(PyObject *self, PyObject *arg)
+{
+ //FIXME: Have a reference count for R objects known to Python.
+ //ending R will not be possible until all such objects are already
+ //deallocated in Python ?
+ //other possibility would be to have a fallback for "unreachable" objects ?
+ //FIXME: rpy has something to terminate R. Check the details of what it is.
+ if (! PyInt_Check(arg)) {
+ } else {
+ /* sanity checks needed ? */
+ const long fatal = PyInt_AsLong(arg);
+ Rf_endEmbeddedR((int)fatal);
+ }
+ Py_RETURN_NONE;
+}
+PyDoc_STRVAR(EmbeddedR_end_doc,
+ "endEmbeddedR()\n\
+\n\
+Terminate an embedded R.");
+
+
+/* --- set output from the R console ---*/
+
+static void
+EmbeddedR_WriteConsole(char *buf, int len)
+{
+ PyOS_sighandler_t old_int;
+
+ /* It is necessary to restore the Python handler when using a Python
+ function for I/O. */
+ old_int = PyOS_getsig(SIGINT);
+ PyOS_setsig(SIGINT, python_sigint);
+ PySys_WriteStdout(buf);
+ signal(SIGINT, old_int);
+}
+
+
+/* Redirect R console output */
+// R_Outputfile = NULL;
+
+
+/* FIXME: implement possibility to specify arbitrary callback functions */
+extern void (*ptr_R_WriteConsole)(char *, int);
+static PyObject* EmbeddedR_setWriteConsole(PyObject *self)
+{
+ ptr_R_WriteConsole = EmbeddedR_WriteConsole;
+ Py_RETURN_NONE;
+}
+PyDoc_STRVAR(EmbeddedR_setWriteConsole_doc,
+ "setWriteConsoleEmbeddedR()\n\
+\n\
+Set the R console output to the Python console.");
+
+
+static PyObject*
+EmbeddedR_exception_from_errmessage(void)
+{
+ //FIXME: sort the error message thing geterrmessage
+ PyErr_SetString(ErrorObject, "Error.");
+ return NULL;
+}
+
+
+
+
+/*
+ * Access to R objects through Python objects
+ */
+
+static void
+Sexp_dealloc(SexpObject *self)
+{
+ if (self->sexp)
+ R_ReleaseObject(self->sexp);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static PyObject*
+Sexp_repr(PyObject *self)
+{
+ return PyString_FromFormat("<%s - Python:\%p / R:\%p>",
+ self->ob_type->tp_name,
+ self,
+ &(((SexpObject *)self)->sexp));
+}
+
+
+static PyObject*
+Sexp_typeof(PyObject *self)
+{
+ return PyInt_FromLong(TYPEOF(((SexpObject*)self)->sexp));
+}
+PyDoc_STRVAR(Sexp_typeof_doc,
+"\n\
+Returns the R internal SEXP type.");
+
+static PyMethodDef Sexp_methods[] = {
+ {"typeof", (PyCFunction)Sexp_typeof, METH_NOARGS,
+ Sexp_typeof_doc},
+ {NULL, NULL} /* sentinel */
+};
+
+
+/*
+ * Generic Sexp_Type. It represents SEXP objects at large.
+ */
+static PyTypeObject Sexp_Type = {
+ /* The ob_type field must be initialized in the module init function
+ * to be portable to Windows without using C++. */
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "rinterface.Sexp", /*tp_name*/
+ sizeof(SexpObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)Sexp_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ Sexp_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0,//Sexp_str, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ 0, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ Sexp_methods, /*tp_methods*/
+ 0, /*tp_members*/
+ 0,//Sexp_getset, /*tp_getset*/
+ 0, /*tp_base*/
+ 0, /*tp_dict*/
+ 0, /*tp_descr_get*/
+ 0, /*tp_descr_set*/
+ 0, /*tp_dictoffset*/
+ 0, /*tp_init*/
+ 0, /*tp_alloc*/
+ 0,//Sexp_new, /*tp_new*/
+ 0, /*tp_free*/
+ 0, /*tp_is_gc*/
+};
+
+
+/*
+ * Closure-type Sexp.
+ */
+
+static SexpObject* newSexpObject(SEXP);
+static SEXP newSEXP(PyObject *object, int rType);
+
+/* Evaluate a SEXP. It must be constructed by hand. It raises a Python
+ exception if an error ocurred in the evaluation */
+SEXP do_eval_expr(SEXP expr_R) {
+ SEXP res_R;
+ int error = 0;
+ PyOS_sighandler_t old_int;
+
+ /* Enable our handler for SIGINT inside the R
+ interpreter. Otherwise, we cannot stop R calculations, since
+ SIGINT is only processed between Python bytecodes. Also, save the
+ Python SIGINT handler because it is necessary to temporally
+ restore it in user defined I/O Python functions. */
+ /* stop_events(); */
+
+#ifdef _WIN32
+ old_int = PyOS_getsig(SIGBREAK);
+#else
+ old_int = PyOS_getsig(SIGINT);
+#endif
+ python_sigint = old_int;
+
+ signal(SIGINT, interrupt_R);
+
+ interrupted = 0;
+ //FIXME: evaluate expression in the given
+ res_R = R_tryEval(expr_R, R_GlobalEnv, &error);
+
+#ifdef _WIN32
+ PyOS_setsig(SIGBREAK, old_int);
+#else
+ PyOS_setsig(SIGINT, old_int);
+#endif
+
+ /* start_events(); */
+
+ if (error) {
+ if (interrupted) {
+ PyErr_SetNone(PyExc_KeyboardInterrupt);
+ //FIXME: handling of interruptions
+ } else {
+ EmbeddedR_exception_from_errmessage();
+ }
+ return NULL;
+ }
+
+ return res_R;
+}
+
+
+/* This is the method to call when invoking an 'Sexp' */
+static PyObject *
+Sexp_call(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ SEXP call_R, c_R, res_R;
+ int largs, lkwds;
+
+ largs = lkwds = 0;
+ if (args)
+ largs = PyObject_Length(args);
+ if (kwds)
+ lkwds = PyObject_Length(kwds);
+ if ((largs<0) || (lkwds<0))
+ return NULL;
+
+ /* 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);
+ SETCAR(c_R, ((SexpObject *)self)->sexp);
+ c_R = CDR(c_R);
+
+ int arg_i;
+ SEXP tmp_R;
+ for (arg_i=0; arg_i<largs; arg_i++) {
+ //FIXME: assert that all are SexpObjects
+ tmp_R = ((SexpObject *)PyTuple_GetItem(args, arg_i))->sexp;
+ SETCAR(c_R, tmp_R);
+ c_R = CDR(c_R);
+ }
+
+/* if (!make_kwds(lkwds, kwds, &e)) { */
+/* UNPROTECT(1); */
+/* return NULL; */
+/* } */
+
+//FIXME: R_GlobalContext ?
+ PROTECT(res_R = do_eval_expr(call_R));
+
+/* if (!res) { */
+/* UNPROTECT(2); */
+/* return NULL; */
+/* } */
+ UNPROTECT(2);
+ //FIXME: standardize R outputs
+ extern void Rf_PrintWarnings(void);
+ Rf_PrintWarnings(); /* show any warning messages */
+
+ PyObject *res = (PyObject *)newSexpObject(res_R);
+ return res;
+}
+
+
+
+
+static SexpObject*
+Sexp_closureEnv(PyObject *self)
+{
+ SEXP closureEnv = CLOENV(((SexpObject*)self)->sexp);
+ return newSexpObject(closureEnv);
+}
+PyDoc_STRVAR(Sexp_closureEnv_doc,
+ "\n\
+Returns the environment the object is defined in.\
+This corresponds to the C-level function CLOENV(SEXP).");
+
+static PyMethodDef ClosureSexp_methods[] = {
+ {"closureEnv", (PyCFunction)Sexp_closureEnv, METH_NOARGS,
+ Sexp_closureEnv_doc},
+ {NULL, NULL} /* sentinel */
+};
+
+//FIXME: write more doc
+PyDoc_STRVAR(ClosureSexp_Type_doc,
+"A R object that is a closure, that is a function. \
+In R a function a function is defined in an enclosing \
+environement, thus the name of closure. \
+\n\
+The closure can be accessed with the method 'closureEnv'.\
+");
+
+static PyTypeObject ClosureSexp_Type = {
+ /* The ob_type field must be initialized in the module init function
+ * to be portable to Windows without using C++. */
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "rinterface.ClosureSexp", /*tp_name*/
+ sizeof(SexpObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ Sexp_call, /*tp_call*/
+ 0,//Sexp_str, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ 0, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ ClosureSexp_methods, /*tp_methods*/
+ 0, /*tp_members*/
+ 0,//Sexp_getset, /*tp_getset*/
+ &Sexp_Type, /*tp_base*/
+ 0, /*tp_dict*/
+ 0, /*tp_descr_get*/
+ 0, /*tp_descr_set*/
+ 0, /*tp_dictoffset*/
+ 0, /*tp_init*/
+ 0, /*tp_alloc*/
+ 0,//Sexp_new, /*tp_new*/
+ 0, /*tp_free*/
+ 0 /*tp_is_gc*/
+};
+
+static PyObject*
+VectorSexp_new(PyTypeObject *type, PyObject *args)
+{
+ int rType = -1;
+ PyObject *seq = 0;
+ if (!PyArg_ParseTuple(args, "iO:new",
+ &rType, &seq))
+ return NULL;
+ #ifdef VERBOSE
+ printf("type: %i\n", rType);
+ #endif
+ SEXP sexp;
+ sexp = newSEXP(seq, rType);
+ PyObject *res = (PyObject *)newSexpObject(sexp);
+ return res;
+}
+
+static Py_ssize_t VectorSexp_len(PyObject *object)
+{
+ Py_ssize_t len;
+ //FIXME: sanity checks.
+ len = (Py_ssize_t)LENGTH(((SexpObject *)object)->sexp);
+ return len;
+}
+
+static PySequenceMethods VectorSexp_sequenceMethods = {
+ (inquiry)VectorSexp_len, /* sq_length */
+ 0, /* sq_concat */
+ 0, /* sq_repeat */
+ //FIXME: implement
+ 0, //(ssizeargfunc)Sexp_item, /* sq_item */
+ //FIXME: implement
+ 0, //(ssizessizeargfunc)Sexp_slice, /* sq_slice */
+ //FIXME: implement
+ 0, //(ssizeobjargproc)Sexp_ass_item, /* sq_ass_item */
+ 0, /* sq_ass_slice */
+ 0, /* sq_contains */
+ 0, /* sq_inplace_concat */
+ 0 /* sq_inplace_repeat */
+};
+
+//FIXME: write more doc
+PyDoc_STRVAR(VectorSexp_Type_doc,
+"An R object that is a vector.\
+ R vectors start their indexing at one,\
+ while Python lists or arrays start indexing\
+ at zero.\
+\n\
+In the hope to avoid confusion, the indexing\
+ from the Python subset operator (__getitem__)\
+ is done at zero.");
+/* ", while an other method to perform\ */
+/* it at one is provided (_not yet implemented_).\ */
+/* That other method is also performing indexing."); */
+//FIXME: implement offset-one indexing.
+
+static PyTypeObject VectorSexp_Type = {
+ /* The ob_type field must be initialized in the module init function
+ * to be portable to Windows without using C++. */
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "rinterface.VectorSexp", /*tp_name*/
+ sizeof(SexpObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &VectorSexp_sequenceMethods, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0,//Sexp_str, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ VectorSexp_Type_doc, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ 0, /*tp_methods*/
+ 0, /*tp_members*/
+ 0,//Sexp_getset, /*tp_getset*/
+ &Sexp_Type, /*tp_base*/
+ 0, /*tp_dict*/
+ 0, /*tp_descr_get*/
+ 0, /*tp_descr_set*/
+ 0, /*tp_dictoffset*/
+ 0, /*tp_init*/
+ 0, /*tp_alloc*/
+ VectorSexp_new, /*tp_new*/
+ 0, /*tp_free*/
+ 0 /*tp_is_gc*/
+};
+
+
+//FIXME: write more doc
+PyDoc_STRVAR(EnvironmentSexp_Type_doc,
+"An R object that is an environment.\
+ R environments can be seen as similar to Python\
+ dictionnaries, with the twist that looking for\
+ a key can be recursively propagated to the enclosing\
+ environment whenever the key is not found.\
+\n\
+ The subsetting operator is made to match Python's\
+ behavior, that is the enclosing environment are not\
+ inspect upon absence of a given key.\
+");
+
+static PyTypeObject EnvironmentSexp_Type = {
+ /* The ob_type field must be initialized in the module init function
+ * to be portable to Windows without using C++. */
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "rinterface.EnvironmentSexp", /*tp_name*/
+ sizeof(SexpObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0,//Sexp_str, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ EnvironmentSexp_Type_doc, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ 0, /*tp_methods*/
+ 0, /*tp_members*/
+ 0,//Sexp_getset, /*tp_getset*/
+ &Sexp_Type, /*tp_base*/
+ 0, /*tp_dict*/
+ 0, /*tp_descr_get*/
+ 0, /*tp_descr_set*/
+ 0, /*tp_dictoffset*/
+ 0, /*tp_init*/
+ 0, /*tp_alloc*/
+ //FIXME: add new method
+ 0, //EnvironmentSexp_new, /*tp_new*/
+ 0, /*tp_free*/
+ 0 /*tp_is_gc*/
+};
+
+
+//FIXME: write more doc
+PyDoc_STRVAR(S4Sexp_Type_doc,
+"An R object that is an 'S4 object'.\
+");
+
+static PyTypeObject S4Sexp_Type = {
+ /* The ob_type field must be initialized in the module init function
+ * to be portable to Windows without using C++. */
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "rinterface.S4Sexp", /*tp_name*/
+ sizeof(SexpObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0,//Sexp_str, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ S4Sexp_Type_doc, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ 0, /*tp_methods*/
+ 0, /*tp_members*/
+ 0,//Sexp_getset, /*tp_getset*/
+ &Sexp_Type, /*tp_base*/
+ 0, /*tp_dict*/
+ 0, /*tp_descr_get*/
+ 0, /*tp_descr_set*/
+ 0, /*tp_dictoffset*/
+ 0, /*tp_init*/
+ 0, /*tp_alloc*/
+ //FIXME: add new method
+ 0, //S4Sexp_new, /*tp_new*/
+ 0, /*tp_free*/
+ 0 /*tp_is_gc*/
+};
+
+
+
+/* --- Create a SEXP object --- */
+static SexpObject*
+newSexpObject(SEXP sexp)
+{
+ SexpObject *object;
+ SEXP env_R;
+
+ //FIXME: let the possibility to manipulate un-evaluated promises ?
+ if (TYPEOF(sexp) == PROMSXP) {
+ #ifdef VERBOSE
+ printf("evaluating promise...");
+ #endif
+ env_R = PRENV(sexp);
+ sexp = eval(sexp, env_R);
+ #ifdef VERBOSE
+ printf("done.\n");
+ #endif
+ }
+
+ switch (TYPEOF(sexp)) {
+ case CLOSXP:
+ object = (SexpObject *)_PyObject_New(&ClosureSexp_Type);
+ break;
+ //FIXME: handle other callable types ?
+ //case SPECIALSXP:
+ //callable type
+ //break;
+ //case BUILTINSXP:
+ //callable type
+ //break;
+ case REALSXP:
+ case INTSXP:
+ case LGLSXP:
+ case STRSXP:
+ object = (SexpObject *)_PyObject_New(&VectorSexp_Type);
+ break;
+ case ENVSXP:
+ object = (SexpObject *)_PyObject_New(&EnvironmentSexp_Type);
+ break;
+ case S4SXP:
+ object = (SexpObject *)_PyObject_New(&S4Sexp_Type);
+ break;
+ default:
+ object = (SexpObject *)_PyObject_New(&Sexp_Type);
+ break;
+ }
+ if (!object)
+ PyErr_NoMemory();
+ object->sexp = sexp;
+ if (sexp)
+ R_PreserveObject(sexp);
+ return object;
+}
+
+static SEXP
+newSEXP(PyObject *object, int rType)
+{
+ SEXP sexp;
+ PyObject *seq_object, *item;
+ seq_object = PySequence_Fast(object, "Cannot create"
+ " R object from non-sequence Python object.");
+ if (! seq_object)
+ return NULL;
+
+ const Py_ssize_t length = PySequence_Fast_GET_SIZE(seq_object);
+ //FIXME: PROTECT THIS
+ #ifdef VERBOSE
+ printf("size: %i", length);
+ #endif
+ sexp = allocVector(rType, length);
+
+ int i;
+
+ switch(rType) {
+ case REALSXP:
+ for (i = 0; i < length; ++i) {
+ if((item = PyNumber_Float(PySequence_Fast_GET_ITEM(seq_object, i)))) {
+ REAL(sexp)[i] = PyFloat_AS_DOUBLE(item);
+ Py_DECREF(item);
+ }
+ else {
+ PyErr_Clear();
+ REAL(sexp)[i] = NA_REAL;
+ }
+ }
+ break;
+ case INTSXP:
+ for (i = 0; i < length; ++i) {
+ if((item = PyNumber_Int(PySequence_Fast_GET_ITEM(seq_object, i)))) {
+ long l = PyInt_AS_LONG(item);
+ INTEGER(sexp)[i] = (l<=INT_MAX && l>=INT_MIN)?l:NA_INTEGER;
+ Py_DECREF(item);
+ }
+ else {
+ PyErr_Clear();
+ INTEGER(sexp)[i] = NA_INTEGER;
+ }
+ }
+ break;
+ case LGLSXP:
+ for (i = 0; i < length; ++i) {
+ int q = PyObject_IsTrue(PySequence_Fast_GET_ITEM(seq_object, i));
+ if (q != -1)
+ LOGICAL(sexp)[i] = q;
+ else {
+ PyErr_Clear();
+ LOGICAL(sexp)[i] = NA_LOGICAL;
+ }
+ }
+ break;
+ case STRSXP:
+ for (i = 0; i < length; ++i) {
+ if((item = PyObject_Str(PySequence_Fast_GET_ITEM(seq_object, i)))) {
+ SEXP str_R = mkChar(PyString_AS_STRING(item));
+ if (!str_R) {
+ PyErr_NoMemory();
+ sexp = NULL;
+ break;
+ }
+ SET_STRING_ELT(sexp, i, str_R);
+ }
+ else {
+ PyErr_Clear();
+ SET_STRING_ELT(sexp, i, NA_STRING);
+ }
+ }
+ break;
+ default:
+ PyErr_Format(PyExc_ValueError, "cannot handle type %d", rType);
+ sexp = NULL;
+ }
+ return sexp;
+}
+
+
+
+static PyObject*
+EmbeddedR_newSexpObject(SEXP sexp)
+{
+ SexpObject *res;
+
+ return (PyObject *)res;
+}
+
+//ClosureSexp_Type.tp_call = &Sexp_call;
+//ClosureSexp_Type.tp_call = 0;
+
+
+//(PyTypeObject *)ClosureSexp_Type.tp_new = 0;//ClosureSexp_methods;
+
+
+static PyObject*
+Sexp_GlobalEnv(PyTypeObject* type)
+{
+ SexpObject* res = (SexpObject*)type->tp_alloc(type, 0);
+ res->sexp = R_GlobalEnv;
+ return (PyObject*)res;
+}
+
+
+
+/* --- Find a variable in an environment --- */
+
+
+static SexpObject*
+EmbeddedR_findVar(PyObject *self, PyObject *args)
+//EmbeddedR_findVar(PyTypeObject *type, PyObject *args)
+{
+ char *name;
+ SEXP rho = R_GlobalEnv, res;
+ PyObject *ErrorObject;
+
+ if (!PyArg_ParseTuple(args, "s", &name)) {
+ //, "s|O&", &name, Get_SEXP, &rho)) {
+ return NULL;
+ }
+ res = findVar(install(name), rho);
+ if (res != R_UnboundValue) {
+ #ifdef VERBOSE
+ printf("found.\n");
+ #endif
+ return newSexpObject(res);
+ }
+ PyErr_Format(ErrorObject, "'%s' not found", name);
+ return NULL;
+}
+PyDoc_STRVAR(EmbeddedR_findVar_doc,
+ "Find a variable in R's .GlobalEnv.");
+
+
+
+
+/* --- List of functions defined in the module --- */
+
+static PyMethodDef EmbeddedR_methods[] = {
+ {"initEmbeddedR", (PyCFunction)EmbeddedR_init, METH_VARARGS,
+ EmbeddedR_init_doc},
+ {"endEmbeddedR", (PyCFunction)EmbeddedR_end, METH_O,
+ EmbeddedR_end_doc},
+ {"setWriteConsole", (PyCFunction)EmbeddedR_setWriteConsole, METH_NOARGS,
+ EmbeddedR_setWriteConsole_doc},
+ {"findVarEmbeddedR", (PyCFunction)EmbeddedR_findVar, METH_VARARGS,
+ EmbeddedR_findVar_doc},
+ {NULL, NULL} /* sentinel */
+};
+
+
+
+
+/* --- Initialize the module ---*/
+
+#define ADD_INT_CONSTANT(module, name) PyModule_AddIntConstant(module, #name,
name)
+
+PyMODINIT_FUNC
+initrinterface(void)
+{
+
+ /* Finalize the type object including setting type of the new type
+ * object; doing it here is required for portability to Windows
+ * without requiring C++. */
+ if (PyType_Ready(&Sexp_Type) < 0)
+ return;
+ if (PyType_Ready(&ClosureSexp_Type) < 0)
+ return;
+ if (PyType_Ready(&VectorSexp_Type) < 0)
+ return;
+
+ PyObject *m;
+ m = Py_InitModule3("rinterface", EmbeddedR_methods, module_doc);
+ if (m == NULL)
+ return;
+
+ PyModule_AddObject(m, "Sexp", (PyObject *)&Sexp_Type);
+ PyModule_AddObject(m, "SexpClosure", (PyObject *)&ClosureSexp_Type);
+ PyModule_AddObject(m, "SexpVector", (PyObject *)&VectorSexp_Type);
+
+ //FIXME: clean the exception stuff
+ if (ErrorObject == NULL) {
+ ErrorObject = PyErr_NewException("rinterface.error", NULL, NULL);
+ if (ErrorObject == NULL)
+ return;
+ }
+ Py_INCREF(ErrorObject);
+ PyModule_AddObject(m, "RobjectNotFound", ErrorObject);
+
+
+ /* Add some symbolic constants to the module */
+ ADD_INT_CONSTANT(m, NILSXP);
+ ADD_INT_CONSTANT(m, SYMSXP);
+ ADD_INT_CONSTANT(m, LISTSXP);
+ ADD_INT_CONSTANT(m, CLOSXP);
+ ADD_INT_CONSTANT(m, ENVSXP);
+ ADD_INT_CONSTANT(m, PROMSXP);
+ ADD_INT_CONSTANT(m, LANGSXP);
+ ADD_INT_CONSTANT(m, SPECIALSXP);
+ ADD_INT_CONSTANT(m, BUILTINSXP);
+ ADD_INT_CONSTANT(m, CHARSXP);
+ ADD_INT_CONSTANT(m, STRSXP);
+ ADD_INT_CONSTANT(m, LGLSXP);
+ ADD_INT_CONSTANT(m, INTSXP);
+ ADD_INT_CONSTANT(m, REALSXP);
+ ADD_INT_CONSTANT(m, CPLXSXP);
+ ADD_INT_CONSTANT(m, DOTSXP);
+ ADD_INT_CONSTANT(m, ANYSXP);
+ ADD_INT_CONSTANT(m, VECSXP);
+ ADD_INT_CONSTANT(m, VECSXP);
+ ADD_INT_CONSTANT(m, EXPRSXP);
+ ADD_INT_CONSTANT(m, BCODESXP);
+ ADD_INT_CONSTANT(m, EXTPTRSXP);
+ ADD_INT_CONSTANT(m, RAWSXP);
+ ADD_INT_CONSTANT(m, S4SXP);
+}
Property changes on: trunk/sandbox/rpy_nextgen/rinterface/rinterface.c
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/sandbox/rpy_nextgen/setup.py
===================================================================
--- trunk/sandbox/rpy_nextgen/setup.py (rev 0)
+++ trunk/sandbox/rpy_nextgen/setup.py 2008-02-23 15:24:21 UTC (rev 404)
@@ -0,0 +1,32 @@
+
+import os, os.path, sys, shutil
+from distutils.core import setup, Extension
+from subprocess import Popen, PIPE
+
+RHOME = os.getenv("R_HOME")
+if RHOME is None:
+ RHOME = Popen(["R", "RHOME"], stdout=PIPE).communicate()[0].strip()
+
+print('R\'s home is:%s' %RHOME)
+
+r_libs = [os.path.join(RHOME, 'lib')]
+
+
+rinterface = Extension(
+ "rinterface",
+ ["rinterface/rinterface.c", ],
+ include_dirs=[ os.path.join(RHOME, 'include'),],
+ libraries=['R'],
+ library_dirs=r_libs,
+ runtime_library_dirs=r_libs,
+ #extra_link_args=[],
+ )
+
+setup(name="rpython",
+ version="0.0.1",
+ description="Python interface to the R language",
+ url="http://rpy.sourceforge.net",
+ license="GPL",
+ ext_modules=[rinterface],
+ #py_modules=['rpython']
+ )
Property changes on: trunk/sandbox/rpy_nextgen/setup.py
___________________________________________________________________
Name: svn:executable
+ *
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
rpy-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rpy-list