[Numpy-svn] r3289 - in trunk/numpy/f2py/lib: . parser
numpy-svn at scipy.org
numpy-svn at scipy.org
Sun Oct 8 02:38:06 EDT 2006
Author: pearu
Date: 2006-10-08 01:37:50 -0500 (Sun, 08 Oct 2006)
New Revision: 3289
Removed:
trunk/numpy/f2py/lib/generate_pyobj_tofrom_funcs.py
Modified:
trunk/numpy/f2py/lib/parser/typedecl_statements.py
trunk/numpy/f2py/lib/py_wrap_subprogram.py
trunk/numpy/f2py/lib/py_wrap_type.py
trunk/numpy/f2py/lib/test_scalar_in_out.py
trunk/numpy/f2py/lib/wrapper_base.py
Log:
F2PY G3: added support and tests for character*(*) types.
Deleted: trunk/numpy/f2py/lib/generate_pyobj_tofrom_funcs.py
===================================================================
--- trunk/numpy/f2py/lib/generate_pyobj_tofrom_funcs.py 2006-10-07 18:05:18 UTC (rev 3288)
+++ trunk/numpy/f2py/lib/generate_pyobj_tofrom_funcs.py 2006-10-08 06:37:50 UTC (rev 3289)
@@ -1,131 +0,0 @@
-"""
-Generate
- int pyobj_to_<ctype>(PyObject* obj, <ctype>* value)
- PyObject* pyobj_from_<stype>(<ctype>* value)
-functions.
-"""
-__all__ = ['pyobj_to_npy_scalar','pyobj_to_f2py_string','pyobj_from_npy_scalar']
-
-from parser.api import CHAR_BIT
-
-def pyobj_from_npy_int(ctype):
- dtype = ctype.upper()
- cls = 'Int'+ctype[7:]
- return '''\
-static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
- PyObject* obj = PyArrayScalar_New(%(cls)s);
- if (obj==NULL) /* TODO: set exception */ return NULL;
- PyArrayScalar_ASSIGN(obj,%(cls)s,*value);
- return obj;
-}
-''' % (locals())
-
-def pyobj_from_npy_float(ctype):
- dtype = ctype.upper()
- cls = 'Float'+ctype[9:]
- return '''\
-/* depends: SCALARS_IN_BITS2.cpp */
-static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
- PyObject* obj = PyArrayScalar_New(%(cls)s);
- if (obj==NULL) /* TODO: set exception */ return NULL;
- PyArrayScalar_ASSIGN(obj,%(cls)s,*value);
- return obj;
-}
-''' % (locals())
-
-def pyobj_from_npy_complex(ctype):
- dtype = ctype.upper()
- cls = 'Complex'+ctype[11:]
- return '''\
-/* depends: SCALARS_IN_BITS2.cpp */
-static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
- PyObject* obj = PyArrayScalar_New(%(cls)s);
- if (obj==NULL) /* TODO: set exception */ return NULL;
- PyArrayScalar_ASSIGN(obj,%(cls)s,*value);
- return obj;
-}
-''' % (locals())
-
-def pyobj_from_f2py_type(ctype):
- ctype_bits = int(ctype[10:])
- raise NotImplementedError,`ctype`
- return '''\
-static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
- fprintf(stderr,"In pyobj_from_%(ctype)s (%%p)\\n", value);
-}
-'''
-
-
-
-def pyobj_to_npy_int(ctype):
- Cls = ctype[4].upper()+ctype[5:]
- ctype_bits = int(ctype[7:])
- CTYPE = ctype.upper()
- return capi_code_template_scalar % (locals())
-
-def pyobj_to_npy_float(ctype):
- Cls = ctype[4].upper()+ctype[5:]
- ctype_bits = int(ctype[9:])
- CTYPE = ctype.upper()
- return capi_code_template_scalar % (locals())
-
-def pyobj_to_npy_complex(ctype):
- ctype_bits = int(ctype[11:])
- cfloat_bits = ctype_bits/2
- return '''
-/* depends: pyobj_to_Py_complex.c */
-#if NPY_BITSOF_DOUBLE >= %(cfloat_bits)s
-static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
- int return_value = 0;
- Py_complex c;
-#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
- fprintf(stderr,"pyobj_to_%(ctype)s(type=%%s)\\n",PyString_AS_STRING(PyObject_Repr(PyObject_Type(obj))));
-#endif
- if (pyobj_to_Py_complex(obj,&c)) {
- (*value).real = (npy_float%(cfloat_bits)s)c.real;
- (*value).imag = (npy_float%(cfloat_bits)s)c.imag;
- return_value = 1;
- }
-#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
- fprintf(stderr,"pyobj_to_%(ctype)s: return_value=%%d, PyErr_Occurred()=%%p\\n", return_value, PyErr_Occurred());
-#endif
- return return_value;
-}
-#else
-#error, "NOTIMPLEMENTED pyobj_to_%(ctype)s"
-#endif
-''' % (locals())
-
-def pyobj_to_npy_scalar(ctype):
- if ctype.startswith('npy_int'):
- return dict(c_code=pyobj_to_npy_int(ctype))
- elif ctype.startswith('npy_float'):
- return dict(c_code=pyobj_to_npy_float(ctype))
- elif ctype.startswith('npy_complex'):
- return dict(c_code=pyobj_to_npy_complex(ctype))
- raise NotImplementedError,`ctype`
-
-def pyobj_to_f2py_string(ctype):
- ctype_bits = int(ctype[11:])
- ctype_bytes = ctype_bits / CHAR_BIT
- return dict(
- c_code = '''
-/* depends: pyobj_to_string_len.c */
-static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
- return pyobj_to_string_len(obj, (f2py_string*)value, %(ctype_bytes)s);
-}
-''' % (locals()),
- typedef = ['typedef char * f2py_string;',
- 'typedef struct { char data[%(ctype_bytes)s]; } %(ctype); ' % (locals())],
- header = ['#include <string.h>'],
- )
-
-def pyobj_from_npy_scalar(ctype):
- if ctype.startswith('npy_int'):
- return dict(c_code=pyobj_from_npy_int(ctype))
- elif ctype.startswith('npy_float'):
- return dict(c_code=pyobj_from_npy_float(ctype))
- elif ctype.startswith('npy_complex'):
- return dict(c_code=pyobj_from_npy_complex(ctype))
- raise NotImplementedError,`ctype`
-
Modified: trunk/numpy/f2py/lib/parser/typedecl_statements.py
===================================================================
--- trunk/numpy/f2py/lib/parser/typedecl_statements.py 2006-10-07 18:05:18 UTC (rev 3288)
+++ trunk/numpy/f2py/lib/parser/typedecl_statements.py 2006-10-08 06:37:50 UTC (rev 3289)
@@ -445,7 +445,10 @@
default_kind = 1
def get_bit_size(self):
- return CHAR_BIT * int(self.get_length()) * int(self.get_kind())
+ length = self.get_length()
+ if length=='*':
+ return 0 # model for character*(*)
+ return CHAR_BIT * int(length) * int(self.get_kind())
def get_c_type(self):
return 'f2py_string%s' % (self.get_bit_size())
Modified: trunk/numpy/f2py/lib/py_wrap_subprogram.py
===================================================================
--- trunk/numpy/f2py/lib/py_wrap_subprogram.py 2006-10-07 18:05:18 UTC (rev 3288)
+++ trunk/numpy/f2py/lib/py_wrap_subprogram.py 2006-10-08 06:37:50 UTC (rev 3289)
@@ -31,10 +31,9 @@
volatile int f2py_success = 1;
%(decl_list)s
static char *capi_kwlist[] = {%(kw_clist+optkw_clist+extrakw_clist+["NULL"])s};
- if (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,
- "%(pyarg_format_elist)s",
- %(["capi_kwlist"]+pyarg_obj_clist)s))
- return NULL;
+ if (PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,
+ "%(pyarg_format_elist)s",
+ %(["capi_kwlist"]+pyarg_obj_clist)s)) {
%(frompyobj_list)s
%(call_list)s
f2py_success = !PyErr_Occurred();
@@ -46,6 +45,7 @@
}
%(clean_call_list)s
%(clean_frompyobj_list)s
+ }
return capi_buildvalue;
}
'''
@@ -79,17 +79,28 @@
self.clean_frompyobj_list = []
args_f = []
+ extra_args_f = []
for argname in block.args:
var = block.a.variables[argname]
typedecl = var.get_typedecl()
PythonCAPIType(parent, typedecl)
ctype = typedecl.get_c_type()
- self.decl_list.append('%s %s;' % (ctype, argname))
+ if ctype=='f2py_string0':
+ self.decl_list.append('%s %s = {NULL,0};' % (ctype, argname))
+ else:
+ self.decl_list.append('%s %s;' % (ctype, argname))
self.kw_list.append('"%s"' % (argname))
self.pyarg_format_list.append('O&')
self.pyarg_obj_list.append('\npyobj_to_%s, &%s' % (ctype, argname))
if 1: # is_scalar
- args_f.append('&'+argname)
+ if ctype=='f2py_string0':
+ args_f.append('%s.data' % argname)
+ extra_args_f.append('%s.len' % argname)
+ self.clean_frompyobj_list.append(\
+ 'if (%s.len) free(%s.data);' % (argname,argname))
+ else:
+ args_f.append('&'+argname)
+
else:
args_f.append(argname)
if var.is_intent_out(): # and is_scalar
@@ -97,7 +108,7 @@
self.return_obj_list.append('\npyobj_from_%s, &%s' % (ctype, argname))
WrapperCPPMacro(parent, 'F_FUNC')
- self.call_list.append('%s_f(%s);' % (name,', '.join(args_f)))
+ self.call_list.append('%s_f(%s);' % (name,', '.join(args_f+extra_args_f)))
self.clean_pyobjfrom_list.reverse()
self.clean_call_list.reverse()
Modified: trunk/numpy/f2py/lib/py_wrap_type.py
===================================================================
--- trunk/numpy/f2py/lib/py_wrap_type.py 2006-10-07 18:05:18 UTC (rev 3288)
+++ trunk/numpy/f2py/lib/py_wrap_type.py 2006-10-08 06:37:50 UTC (rev 3289)
@@ -238,6 +238,52 @@
#endif
return return_value;
}
+'''
+ capi_code_template_string0_scalar = '''
+static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_from_%(ctype)s(value->len=%%d, value->data=\'%%s\')\\n",value->len, value->data);
+#endif
+ PyArray_Descr* descr = PyArray_DescrNewFromType(NPY_STRING);
+ descr->elsize = value->len;
+ PyObject* obj = PyArray_Scalar(value->data, descr, NULL);
+ if (obj==NULL) /* TODO: set exception */ return NULL;
+ return obj;
+}
+
+static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
+ int return_value = 0;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_to_%(ctype)s(type=%%s)\\n",PyString_AS_STRING(PyObject_Repr(PyObject_Type(obj))));
+#endif
+ if (PyString_Check(obj)) {
+ value->len = PyString_GET_SIZE(obj);
+ value->data = malloc(value->len*sizeof(char));
+ return_value = !! strncpy(value->data,PyString_AS_STRING(obj),value->len);
+ } else {
+ return_value = pyobj_to_%(ctype)s(PyObject_Str(obj), value);
+ }
+ if (!return_value && !PyErr_Occurred()) {
+ PyObject* r = PyString_FromString("Failed to convert ");
+ PyString_ConcatAndDel(&r, PyObject_Repr(PyObject_Type(obj)));
+ PyString_ConcatAndDel(&r, PyString_FromString(" to C %(ctype)s"));
+ PyErr_SetObject(PyExc_TypeError,r);
+ }
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ if (PyErr_Occurred()) {
+ if (return_value)
+ fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+ else
+ fprintf(stderr,"pyobj_to_%(ctype)s: PyErr_Occurred()=%%p\\n", PyErr_Occurred());
+ } else {
+ if (return_value)
+ fprintf(stderr,"pyobj_to_%(ctype)s: value->len=%%d, value->data=\'%%s\'\\n", value->len, value->data);
+ else
+ fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+ }
+#endif
+ return return_value;
+}
'''
_defined = []
def __init__(self, parent, typedecl):
@@ -270,12 +316,21 @@
self.capi_code_template = self.capi_code_template_logical_scalar
parent.apply_templates(self)
return
+ if ctype == 'f2py_string0':
+ self.header_template = '''
+#include <string.h>
+typedef struct { char* data; size_t len; } %(ctype)s;
+'''
+ self.capi_code_template = self.capi_code_template_string0_scalar
+ parent.apply_templates(self)
+ return
+ raise NotImplementedError,`name,ctype`
if ctype.startswith('f2py_string'):
self.bits = bits = int(ctype[11:])
self.bytes = bits/CHAR_BIT
self.header_template = '''
#include <string.h>
-typedef struct { char data[%(bytes)s] } %(ctype)s;
+typedef struct { char data[%(bytes)s]; } %(ctype)s;
'''
self.capi_code_template = self.capi_code_template_string_scalar
parent.apply_templates(self)
Modified: trunk/numpy/f2py/lib/test_scalar_in_out.py
===================================================================
--- trunk/numpy/f2py/lib/test_scalar_in_out.py 2006-10-07 18:05:18 UTC (rev 3288)
+++ trunk/numpy/f2py/lib/test_scalar_in_out.py 2006-10-08 06:37:50 UTC (rev 3289)
@@ -1,5 +1,8 @@
#!/usr/bin/env python
+"""
+"""
+
import os
import sys
from numpy.testing import *
@@ -100,6 +103,13 @@
!f2py intent(in,out) a
a(1:2) = "12"
end
+ subroutine foostringstar(a)
+ character*(*) a
+!f2py intent(in,out) a
+ if (len(a).gt.0) then
+ a(1:1) = "1"
+ endif
+ end
'''
# tester note: set rebuild=True when changing fortan_code and for SVN
@@ -518,6 +528,15 @@
r = func([1])
assert isinstance(r,string0),`type(r)`
assert_equal(r,'12] ')
+
+ def check_foo_string0(self, level=1):
+ i = string0('abcde')
+ e = string0('12cde')
+ func = m.foostringstar
+ r = func('abcde')
+ assert_equal(r,'1bcde')
+ r = func('')
+ assert_equal(r,'')
if __name__ == "__main__":
NumpyTest().run()
Modified: trunk/numpy/f2py/lib/wrapper_base.py
===================================================================
--- trunk/numpy/f2py/lib/wrapper_base.py 2006-10-07 18:05:18 UTC (rev 3288)
+++ trunk/numpy/f2py/lib/wrapper_base.py 2006-10-08 06:37:50 UTC (rev 3289)
@@ -109,7 +109,9 @@
def apply_templates(self, child):
for n in self.list_names:
l = getattr(self,n + '_list')
- l.append(child.apply_attributes(getattr(child, n+'_template','')))
+ c = child.apply_attributes(getattr(child, n+'_template',''))
+ if c:
+ l.append(c)
return
class WrapperCPPMacro(WrapperBase):
More information about the Numpy-svn
mailing list