Author: Armin Rigo <[email protected]>
Branch:
Changeset: r1184:d23457c0c5d3
Date: 2013-03-07 10:25 +0100
http://bitbucket.org/cffi/cffi/changeset/d23457c0c5d3/
Log: Kill the logic to support FILE. Found out that it seems reasonable
enough to use the standard cffi way.
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -90,7 +90,6 @@
#define CT_CUSTOM_FIELD_POS 32768
#define CT_IS_LONGDOUBLE 65536
#define CT_IS_BOOL 131072
-#define CT_IS_FILE 262144
#define CT_PRIMITIVE_ANY (CT_PRIMITIVE_SIGNED | \
CT_PRIMITIVE_UNSIGNED | \
CT_PRIMITIVE_CHAR | \
@@ -211,10 +210,6 @@
#include "minibuffer.h"
-#if PY_MAJOR_VERSION >= 3
-# include "file_emulator.h"
-#endif
-
#ifdef HAVE_WCHAR_H
# include "wchar_helper.h"
#endif
@@ -2085,12 +2080,6 @@
/* from a unicode, we add the null terminator */
length = _my_PyUnicode_SizeAsWideChar(init) + 1;
}
- else if ((ctitem->ct_flags & CT_IS_FILE) && PyFile_Check(init)) {
- *output_data = (char *)PyFile_AsFile(init);
- if (*output_data == NULL && PyErr_Occurred())
- return -1;
- return 0;
- }
else {
/* refuse to receive just an integer (and interpret it
as the array size) */
@@ -2785,14 +2774,6 @@
return new_simple_cdata(cdsrc->c_data, ct);
}
}
- if ((ct->ct_flags & CT_POINTER) &&
- (ct->ct_itemdescr->ct_flags & CT_IS_FILE) &&
- PyFile_Check(ob)) {
- FILE *f = PyFile_AsFile(ob);
- if (f == NULL && PyErr_Occurred())
- return NULL;
- return new_simple_cdata((char *)f, ct);
- }
value = _my_PyLong_AsUnsignedLongLong(ob, 0);
if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
return NULL;
@@ -3337,14 +3318,9 @@
static PyObject *b_new_struct_type(PyObject *self, PyObject *args)
{
char *name;
- int flag;
if (!PyArg_ParseTuple(args, "s:new_struct_type", &name))
return NULL;
-
- flag = CT_STRUCT;
- if (strcmp(name, "_IO_FILE") == 0 || strcmp(name, "$FILE") == 0)
- flag |= CT_IS_FILE;
- return _b_struct_or_union_type("struct", name, flag);
+ return _b_struct_or_union_type("struct", name, CT_STRUCT);
}
static PyObject *b_new_union_type(PyObject *self, PyObject *args)
@@ -4923,15 +4899,8 @@
static char *_cffi_to_c_pointer(PyObject *obj, CTypeDescrObject *ct)
{
char *result;
- if (convert_from_object((char *)&result, ct, obj) < 0) {
- if ((ct->ct_flags & CT_POINTER) &&
- (ct->ct_itemdescr->ct_flags & CT_IS_FILE) &&
- PyFile_Check(obj)) {
- PyErr_Clear();
- return (char *)PyFile_AsFile(obj);
- }
+ if (convert_from_object((char *)&result, ct, obj) < 0)
return NULL;
- }
return result;
}
@@ -5130,8 +5099,6 @@
init_errno();
#if PY_MAJOR_VERSION >= 3
- if (init_file_emulator() < 0)
- INITERROR;
return m;
#endif
}
diff --git a/c/file_emulator.h b/c/file_emulator.h
deleted file mode 100644
--- a/c/file_emulator.h
+++ /dev/null
@@ -1,87 +0,0 @@
-
-/* Emulation of PyFile_Check() and PyFile_AsFile() for Python 3. */
-
-static PyObject *PyIOBase_TypeObj;
-
-static int init_file_emulator(void)
-{
- PyObject *io = PyImport_ImportModule("_io");
- if (io == NULL)
- return -1;
- PyIOBase_TypeObj = PyObject_GetAttrString(io, "_IOBase");
- if (PyIOBase_TypeObj == NULL)
- return -1;
- return 0;
-}
-
-
-#define PyFile_Check(p) PyObject_IsInstance(p, PyIOBase_TypeObj)
-
-
-static void _close_file_capsule(PyObject *ob_capsule)
-{
- FILE *f = (FILE *)PyCapsule_GetPointer(ob_capsule, "FILE");
- if (f != NULL)
- fclose(f);
-}
-
-
-static FILE *PyFile_AsFile(PyObject *ob_file)
-{
- PyObject *ob, *ob_capsule = NULL, *ob_mode = NULL;
- FILE *f = NULL;
- int fd;
- char *mode;
-
- ob = PyObject_CallMethod(ob_file, "flush", NULL);
- if (ob == NULL)
- goto fail;
- Py_DECREF(ob);
-
- ob_capsule = PyObject_GetAttrString(ob_file, "__cffi_FILE");
- if (ob_capsule == NULL) {
- PyErr_Clear();
-
- fd = PyObject_AsFileDescriptor(ob_file);
- if (fd < 0)
- goto fail;
-
- ob_mode = PyObject_GetAttrString(ob_file, "mode");
- if (ob_mode == NULL)
- goto fail;
- mode = PyText_AsUTF8(ob_mode);
- if (mode == NULL)
- goto fail;
-
- fd = dup(fd);
- if (fd < 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto fail;
- }
-
- f = fdopen(fd, mode);
- if (f == NULL) {
- close(fd);
- PyErr_SetFromErrno(PyExc_OSError);
- goto fail;
- }
- setbuf(f, NULL); /* non-buffered */
- Py_DECREF(ob_mode);
- ob_mode = NULL;
-
- ob_capsule = PyCapsule_New(f, "FILE", _close_file_capsule);
- if (ob_capsule == NULL) {
- fclose(f);
- goto fail;
- }
-
- if (PyObject_SetAttrString(ob_file, "__cffi_FILE", ob_capsule) < 0)
- goto fail;
- }
- return PyCapsule_GetPointer(ob_capsule, "FILE");
-
- fail:
- Py_XDECREF(ob_mode);
- Py_XDECREF(ob_capsule);
- return NULL;
-}
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -2508,6 +2508,7 @@
pass # win32
def test_FILE():
+ """FILE is not supported natively any more."""
if sys.platform == "win32":
py.test.skip("testing FILE not implemented")
#
@@ -2517,83 +2518,17 @@
BCharP = new_pointer_type(BChar)
BInt = new_primitive_type("int")
BFunc = new_function_type((BCharP, BFILEP), BInt, False)
- BFunc2 = new_function_type((BFILEP, BCharP), BInt, True)
ll = find_and_load_library('c')
fputs = ll.load_function(BFunc, "fputs")
- fscanf = ll.load_function(BFunc2, "fscanf")
#
import posix
fdr, fdw = posix.pipe()
fr1 = posix.fdopen(fdr, 'rb', 256)
fw1 = posix.fdopen(fdw, 'wb', 256)
- #
- fw1.write(b"X")
- res = fputs(b"hello world\n", fw1)
- assert res >= 0
- fw1.flush() # should not be needed
- #
- p = newp(new_array_type(BCharP, 100), None)
- res = fscanf(fr1, b"%s\n", p)
- assert res == 1
- assert string(p) == b"Xhello"
+ py.test.raises(TypeError, fputs, b"hello world\n", fw1)
fr1.close()
fw1.close()
-def test_FILE_only_for_FILE_arg():
- if sys.platform == "win32":
- py.test.skip("testing FILE not implemented")
- #
- B_NOT_FILE = new_struct_type("NOT_FILE")
- B_NOT_FILEP = new_pointer_type(B_NOT_FILE)
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BCharP, B_NOT_FILEP), BInt, False)
- ll = find_and_load_library('c')
- fputs = ll.load_function(BFunc, "fputs")
- #
- import posix
- fdr, fdw = posix.pipe()
- fr1 = posix.fdopen(fdr, 'r')
- fw1 = posix.fdopen(fdw, 'w')
- #
- e = py.test.raises(TypeError, fputs, b"hello world\n", fw1)
- assert str(e.value).startswith(
- "initializer for ctype 'struct NOT_FILE *' must "
- "be a cdata pointer, not ")
-
-def test_FILE_object():
- if sys.platform == "win32":
- py.test.skip("testing FILE not implemented")
- #
- BFILE = new_struct_type("$FILE")
- BFILEP = new_pointer_type(BFILE)
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BCharP, BFILEP), BInt, False)
- BFunc2 = new_function_type((BFILEP,), BInt, False)
- ll = find_and_load_library('c')
- fputs = ll.load_function(BFunc, "fputs")
- fileno = ll.load_function(BFunc2, "fileno")
- #
- import posix
- fdr, fdw = posix.pipe()
- fw1 = posix.fdopen(fdw, 'wb', 256)
- #
- fw1p = cast(BFILEP, fw1)
- fw1.write(b"X")
- fw1.flush()
- res = fputs(b"hello\n", fw1p)
- assert res >= 0
- res = fileno(fw1p)
- assert (res == fdw) == (sys.version_info < (3,))
- fw1.close()
- #
- data = posix.read(fdr, 256)
- assert data == b"Xhello\n"
- posix.close(fdr)
-
def test_GetLastError():
if sys.platform != "win32":
py.test.skip("GetLastError(): only for Windows")
diff --git a/cffi/commontypes.py b/cffi/commontypes.py
--- a/cffi/commontypes.py
+++ b/cffi/commontypes.py
@@ -3,7 +3,7 @@
COMMON_TYPES = {
- 'FILE': model.unknown_type('FILE', '_IO_FILE'),
+ 'FILE': model.unknown_type('FILE'),
'bool': '_Bool',
}
diff --git a/demo/file1.py b/demo/file1.py
new file mode 100644
--- /dev/null
+++ b/demo/file1.py
@@ -0,0 +1,29 @@
+import cffi
+import os
+
+
+ffi = cffi.FFI()
+
+ffi.cdef("""
+FILE *fdopen(int, const char *);
+int fclose(FILE *);
+void dumpme(FILE *);
+""")
+
+lib = ffi.verify("""
+void dumpme(FILE *f) {
+ char c = 'X';
+ fwrite(&c, 1, 1, f);
+}
+""")
+
+
+
+pipe_in, pipe_out = os.pipe()
+
+file_out = lib.fdopen(pipe_out, "w")
+lib.dumpme(file_out)
+lib.fclose(file_out)
+
+x = os.read(pipe_in, 10)
+assert x == 'X'
diff --git a/testing/test_function.py b/testing/test_function.py
--- a/testing/test_function.py
+++ b/testing/test_function.py
@@ -316,20 +316,3 @@
m = ffi.dlopen("m")
x = m.sin(1.23)
assert x == math.sin(1.23)
-
- def test_fputs_custom_FILE(self):
- if self.Backend is CTypesBackend:
- py.test.skip("FILE not supported with the ctypes backend")
- filename = str(udir.join('fputs_custom_FILE'))
- ffi = FFI(backend=self.Backend())
- ffi.cdef("int fputs(const char *, FILE *);")
- C = ffi.dlopen(None)
- with open(filename, 'wb') as f:
- f.write(b'[')
- C.fputs(b"hello from custom file", f)
- f.write(b'][')
- C.fputs(b"some more output", f)
- f.write(b']')
- with open(filename, 'rb') as f:
- res = f.read()
- assert res == b'[hello from custom file][some more output]'
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -1339,7 +1339,14 @@
if sys.platform == 'win32':
py.test.skip("MSVC: cannot assign to stdout")
ffi = FFI()
- ffi.cdef("int printf(const char *, ...); FILE *setstdout(FILE *);")
+ ffi.cdef("""
+ FILE *fdopen(int, const char *);
+ int fclose(FILE *);
+ size_t fwrite(const void *ptr, size_t size, size_t nmemb,
+ FILE *stream);
+ int printf(const char *, ...);
+ FILE *setstdout(FILE *);
+ """)
lib = ffi.verify("""
#include <stdio.h>
FILE *setstdout(FILE *f) {
@@ -1350,13 +1357,13 @@
""")
import os
fdr, fdw = os.pipe()
- fw1 = os.fdopen(fdw, 'wb', 256)
+ fw1 = lib.fdopen(fdw, 'wb')
old_stdout = lib.setstdout(fw1)
try:
#
- fw1.write(b"X")
+ lib.fwrite(b"X", 1, 1, fw1)
r = lib.printf(b"hello, %d!\n", ffi.cast("int", 42))
- fw1.close()
+ lib.fclose(fw1)
assert r == len("hello, 42!\n")
#
finally:
@@ -1364,35 +1371,7 @@
#
result = os.read(fdr, 256)
os.close(fdr)
- # the 'X' might remain in the user-level buffer of 'fw1' and
- # end up showing up after the 'hello, 42!\n'
- assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
-
-def test_FILE_stored_explicitly():
- ffi = FFI()
- ffi.cdef("int myprintf(const char *, int); FILE *myfile;")
- lib = ffi.verify("""
- #include <stdio.h>
- FILE *myfile;
- int myprintf(const char *out, int value) {
- return fprintf(myfile, out, value);
- }
- """)
- import os
- fdr, fdw = os.pipe()
- fw1 = os.fdopen(fdw, 'wb', 256)
- lib.myfile = ffi.cast("FILE *", fw1)
- #
- fw1.write(b"X")
- r = lib.myprintf(b"hello, %d!\n", ffi.cast("int", 42))
- fw1.close()
- assert r == len("hello, 42!\n")
- #
- result = os.read(fdr, 256)
- os.close(fdr)
- # the 'X' might remain in the user-level buffer of 'fw1' and
- # end up showing up after the 'hello, 42!\n'
- assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
+ assert result == b"Xhello, 42!\n"
def test_global_array_with_missing_length():
ffi = FFI()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit