#define FORTRANOBJECT_C
#include "fortranobject.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#include <string.h>
/*
This file implements: FortranObject, array_from_pyobj, copy_ND_array
Author: Pearu Peterson <pearu@cens.ioc.ee>
$Revision: 1.52 $
$Date: 2005/07/11 07:44:20 $
*/
int
F2PyDict_SetItemString(PyObject *dict, char *name, PyObject *obj)
{
if (obj==NULL) {
fprintf(stderr, "Error loading %s\n", name);
if (PyErr_Occurred()) {
PyErr_Print();
PyErr_Clear();
}
return -1;
}
return PyDict_SetItemString(dict, name, obj);
}
/************************* FortranObject *******************************/
typedef PyObject *(*fortranfunc)(PyObject *,PyObject *,PyObject *,void *);
PyObject *
PyFortranObject_New(FortranDataDef* defs, f2py_void_func init) {
int i;
PyFortranObject *fp = NULL;
PyObject *v = NULL;
if (init!=NULL) /* Initialize F90 module objects */
(*(init))();
if ((fp = PyObject_New(PyFortranObject, &PyFortran_Type))==NULL) return NULL;
if ((fp->dict = PyDict_New())==NULL) return NULL;
fp->len = 0;
while (defs[fp->len].name != NULL) fp->len++;
if (fp->len == 0) goto fail;
fp->defs = defs;
for (i=0;i<fp->len;i++)
if (fp->defs[i].rank == -1) { /* Is Fortran routine */
v = PyFortranObject_NewAsAttr(&(fp->defs[i]));
if (v==NULL) return NULL;
PyDict_SetItemString(fp->dict,fp->defs[i].name,v);
} else
if ((fp->defs[i].data)!=NULL) { /* Is Fortran variable or array (not allocatable) */
if (fp->defs[i].type == NPY_STRING) {
int n = fp->defs[i].rank-1;
v = PyArray_New(&PyArray_Type, n, fp->defs[i].dims.d,
NPY_STRING, NULL, fp->defs[i].data, fp->defs[i].dims.d[n],
NPY_ARRAY_FARRAY, NULL);
}
else {
v = PyArray_New(&PyArray_Type, fp->defs[i].rank, fp->defs[i].dims.d,
fp->defs[i].type, NULL, fp->defs[i].data, 0, NPY_ARRAY_FARRAY,
NULL);
}
if (v==NULL) return NULL;
PyDict_SetItemString(fp->dict,fp->defs[i].name,v);
}
Py_XDECREF(v);
return (PyObject *)fp;
fail:
Py_XDECREF(v);
return NULL;
}
PyObject *
PyFortranObject_NewAsAttr(FortranDataDef* defs) { /* used for calling F90 module routines */
PyFortranObject *fp = NULL;
fp = PyObject_New(PyFortranObject, &PyFortran_Type);
if (fp == NULL) return NULL;
if ((fp->dict = PyDict_New())==NULL) {
PyObject_Del(fp);
return NULL;
}
fp->len = 1;
fp->defs = defs;
return (PyObject *)fp;
}
/* Fortran methods */
static void
fortran_dealloc(PyFortranObject *fp) {
Py_XDECREF(fp->dict);
PyObject_Del(fp);
}
#if PY_VERSION_HEX >= 0x03000000
#else
static PyMethodDef fortran_methods[] = {
{NULL, NULL} /* sentinel */
};
#endif
/* Returns number of bytes consumed from buf, or -1 on error. */
static Py_ssize_t
format_def(char *buf, Py_ssize_t size, FortranDataDef def)
{
char *p = buf;
int i, n;
n = PyOS_snprintf(p, size, "array(%" NPY_INTP_FMT, def.dims.d[0]);
if (n < 0 || n >= size) {
return -1;
}
p += n;
size -= n;
for (i = 1; i < def.rank; i++) {
n = PyOS_snprintf(p, size, ",%" NPY_INTP_FMT, def.dims.d[i]);
if (n < 0 || n >= size) {
return -1;
}
p += n;
size -= n;
}
if (size <= 0) {
return -1;
}
*p++ = ')';
size--;
if (def.data == NULL) {
static const char notalloc[] = ", not allocated";
if ((size_t) size < sizeof(notalloc)) {
return -1;
}
memcpy(p, notalloc, sizeof(notalloc));
}
return p - buf;
}
static PyObject *
fortran_doc(FortranDataDef def)
{
char *buf, *p;
PyObject *s = NULL;
Py_ssize_t n, origsize, size = 100;
if (def.doc != NULL) {
size += strlen(def.doc);
}
origsize = size;
buf = p = (char *)PyMem_Malloc(size);
if (buf == NULL) {
return PyErr_NoMemory();
}
if (def.rank == -1) {
if (def.doc) {
n = strlen(def.doc);
if (n > size) {
goto fail;
}
memcpy(p, def.doc, n);
p += n;
size -= n;
}
else {
n = PyOS_snprintf(p, size, "%s - no docs available", def.name);
if (n < 0 || n >= size) {
goto fail;
}
p += n;
size -= n;
}
}
else {
PyArray_Descr *d = PyArray_DescrFromType(def.type);
n = PyOS_snprintf(p, size, "'%c'-", d->type);
Py_DECREF(d);
if (n < 0 || n >= size) {
goto fail;
}
p += n;
size -= n;
if (def.data == NULL) {
n = format_def(p, size, def) == -1;
if (n < 0) {
goto fail;
}
p += n;
size -= n;
}
else if (def.rank > 0) {
n = format_def(p, size, def);
if (n < 0) {
goto fail;
}
p += n;
size -= n;
}
else {
n = strlen("scalar");
if (size < n) {
goto fail;
}
memcpy(p, "scalar", n);
p += n;
size -= n;
}
}
if (size <= 1) {
goto fail;
}
*p++ = '\n';
size--;
/* p now points one beyond the last character of the string in buf */
#if PY_VERSION_HEX >= 0x03000000
s = PyUnicode_FromStringAndSize(buf, p - buf);
#else
s = PyString_FromStringAndSize(buf, p - buf);
#endif
PyMem_Free(buf);
return s;
fail:
fprintf(stderr, "fortranobject.c: fortran_doc: len(p)=%zd>%zd=size:"
" too long docstring required, increase size\n",
p - buf, origsize);
PyMem_Free(buf);
return NULL;
}
static FortranDataDef *save_def; /* save pointer of an allocatable array */
static void set_data(char *d,npy_intp *f) { /* callback from Fortran */
if (*f) /* In fortran f=allocated(d) */
save_def->data = d;
else
save_def->data = NULL;
/* printf("set_data: d=%p,f=%d\n",d,*f); */
}
static PyObject *
fortran_getattr(PyFortranObject *fp, char *name) {
int i,j,k,flag;
if (fp->dict != NULL) {
PyObject *v = PyDict_GetItemString(fp->dict, name);
if (v != NULL) {
Py_INCREF(v);
return v;
}
}
for (i=0,j=1;i<fp->len && (j=strcmp(name,fp->defs[i].name));i++);
if (j==0)
if (fp->defs[i].rank!=-1) { /* F90 allocatable array */
if (fp->defs[i].func==NULL) return NULL;
for(k=0;k<fp->defs[i].rank;++k)
fp->defs[i].dims.d[k]=-1;
save_def = &fp->defs[i];
(*(fp->defs[i].func))(&fp->defs[i].rank,fp->defs[i].dims.d,set_data,&flag);
if (flag==2)
k = fp->defs[i].rank + 1;
else
k = fp->defs[i].rank;
if (fp->defs[i].data !=NULL) { /* array is allocated */
PyObject *v = PyArray_New(&PyArray_Type, k, fp->defs[i].dims.d,
fp->defs[i].type, NULL, fp->defs[i].data, 0, NPY_ARRAY_FARRAY,
NULL);
if (v==NULL) return NULL;
/* Py_INCREF(v); */
return v;
} else { /* array is not allocated */
Py_RETURN_NONE;
}
}
if (strcmp(name,"__dict__")==0) {
Py_INCREF(fp->dict);
return fp->dict;
}
if (strcmp(name,"__doc__")==0) {
#if PY_VERSION_HEX >= 0x03000000
PyObject *s = PyUnicode_FromString(""), *s2, *s3;
for (i=0;i<fp->len;i++) {
s2 = fortran_doc(fp->defs[i]);
s3 = PyUnicode_Concat(s, s2);
Py_DECREF(s2);
Py_DECREF(s);
s = s3;
}
#else
PyObject *s = PyString_FromString("");
for (i=0;i<fp->len;i++)
PyString_ConcatAndDel(&s,fortran_doc(fp->defs[i]));
#endif
if (PyDict_SetItemString(fp->dict, name, s))
return NULL;
return s;
}
if ((strcmp(name,"_cpointer")==0) && (fp->len==1)) {
PyObject *cobj = F2PyCapsule_FromVoidPtr((void *)(fp->defs[0].data),NULL);
if (PyDict_SetItemString(fp->dict, name, cobj))
return NULL;
return cobj;
}
#if PY_VERSION_HEX >= 0x03000000
if (1) {
PyObject *str, *ret;
str = PyUnicode_FromString(name);
ret = PyObject_GenericGetAttr((PyObject *)fp, str);
Py_DECREF(str);
return ret;
}
#else
return Py_FindMethod(fortran_methods, (PyObject *)fp, name);
#endif
}
static int
fortran_setattr(PyFortranObject *fp, char *name, PyObject *v) {
int i,j,flag;
PyArrayObject *arr = NULL;
for (i=0,j=1;i<fp->len && (j=strcmp(name,fp->defs[i].name));i++);
if (j==0) {
if (fp->defs[i].rank==-1) {
PyErr_SetString(PyExc_AttributeError,"over-writing fortran routine");
return -1;
}
if (fp->defs[i].func!=NULL) { /* is allocatable array */
npy_intp dims[F2PY_MAX_DIMS];
int k;
save_def = &fp->defs[i];
if (v!=Py_None) { /* set new value (reallocate if needed --
see f2py generated code for more
details ) */
Loading ...