Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build fails on OS X with NumPy 1.9 #2705

Merged
merged 1 commit into from Jan 14, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/_backend_agg.cpp
Expand Up @@ -2141,13 +2141,14 @@ RendererAgg::write_rgba(const Py::Tuple& args)
args.verify_length(1);

FILE *fp = NULL;
mpl_off_t offset;
Py::Object py_fileobj = Py::Object(args[0]);
PyObject* py_file = NULL;
bool close_file = false;

if (py_fileobj.isString())
{
if ((py_file = npy_PyFile_OpenFile(py_fileobj.ptr(), (char *)"wb")) == NULL) {
if ((py_file = mpl_PyFile_OpenFile(py_fileobj.ptr(), (char *)"wb")) == NULL) {
throw Py::Exception();
}
}
Expand All @@ -2156,28 +2157,28 @@ RendererAgg::write_rgba(const Py::Tuple& args)
py_file = py_fileobj.ptr();
}

if ((fp = npy_PyFile_Dup(py_file, (char *)"wb")))
if ((fp = mpl_PyFile_Dup(py_file, (char *)"wb", &offset)))
{
if (fwrite(pixBuffer, 1, NUMBYTES, fp) != NUMBYTES)
{
if (npy_PyFile_DupClose(py_file, fp)) {
if (mpl_PyFile_DupClose(py_file, fp, offset)) {
throw Py::RuntimeError("Error closing dupe file handle");
}

if (close_file) {
npy_PyFile_CloseFile(py_file);
mpl_PyFile_CloseFile(py_file);
Py_DECREF(py_file);
}

throw Py::RuntimeError("Error writing to file");
}

if (npy_PyFile_DupClose(py_file, fp)) {
if (mpl_PyFile_DupClose(py_file, fp, offset)) {
throw Py::RuntimeError("Error closing dupe file handle");
}

if (close_file) {
npy_PyFile_CloseFile(py_file);
mpl_PyFile_CloseFile(py_file);
Py_DECREF(py_file);
}
}
Expand Down
22 changes: 12 additions & 10 deletions src/_png.cpp
Expand Up @@ -105,6 +105,7 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
args.verify_length(4, 5);

FILE *fp = NULL;
mpl_off_t offset;
bool close_file = false;
bool close_dup_file = false;
Py::Object buffer_obj = Py::Object(args[0]);
Expand Down Expand Up @@ -134,7 +135,7 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
PyObject* py_file = NULL;
if (py_fileobj.isString())
{
if ((py_file = npy_PyFile_OpenFile(py_fileobj.ptr(), (char *)"wb")) == NULL) {
if ((py_file = mpl_PyFile_OpenFile(py_fileobj.ptr(), (char *)"wb")) == NULL) {
throw Py::Exception();
}
close_file = true;
Expand All @@ -144,7 +145,7 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
py_file = py_fileobj.ptr();
}

if ((fp = npy_PyFile_Dup(py_file, (char *)"wb")))
if ((fp = mpl_PyFile_Dup(py_file, (char *)"wb", &offset)))
{
close_dup_file = true;
}
Expand Down Expand Up @@ -240,14 +241,14 @@ Py::Object _png_module::write_png(const Py::Tuple& args)

if (close_dup_file)
{
if (npy_PyFile_DupClose(py_file, fp)) {
if (mpl_PyFile_DupClose(py_file, fp, offset)) {
throw Py::RuntimeError("Error closing dupe file handle");
}
}

if (close_file)
{
npy_PyFile_CloseFile(py_file);
mpl_PyFile_CloseFile(py_file);
Py_DECREF(py_file);
}
/* Changed calls to png_destroy_write_struct to follow
Expand All @@ -261,14 +262,14 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
delete [] row_pointers;
if (close_dup_file)
{
if (npy_PyFile_DupClose(py_file, fp)) {
if (mpl_PyFile_DupClose(py_file, fp, offset)) {
throw Py::RuntimeError("Error closing dupe file handle");
}
}

if (close_file)
{
npy_PyFile_CloseFile(py_file);
mpl_PyFile_CloseFile(py_file);
Py_DECREF(py_file);
}

Expand Down Expand Up @@ -312,21 +313,22 @@ _png_module::_read_png(const Py::Object& py_fileobj, const bool float_result,
{
png_byte header[8]; // 8 is the maximum size that can be checked
FILE* fp = NULL;
mpl_off_t offset;
bool close_file = false;
bool close_dup_file = false;
PyObject *py_file = NULL;

if (py_fileobj.isString())
{
if ((py_file = npy_PyFile_OpenFile(py_fileobj.ptr(), (char *)"rb")) == NULL) {
if ((py_file = mpl_PyFile_OpenFile(py_fileobj.ptr(), (char *)"rb")) == NULL) {
throw Py::Exception();
}
close_file = true;
} else {
py_file = py_fileobj.ptr();
}

if ((fp = npy_PyFile_Dup(py_file, "rb")))
if ((fp = mpl_PyFile_Dup(py_file, "rb", &offset)))
{
close_dup_file = true;
}
Expand Down Expand Up @@ -574,14 +576,14 @@ _png_module::_read_png(const Py::Object& py_fileobj, const bool float_result,
#endif
if (close_dup_file)
{
if (npy_PyFile_DupClose(py_file, fp)) {
if (mpl_PyFile_DupClose(py_file, fp, offset)) {
throw Py::RuntimeError("Error closing dupe file handle");
}
}

if (close_file)
{
npy_PyFile_CloseFile(py_file);
mpl_PyFile_CloseFile(py_file);
Py_DECREF(py_file);
}

Expand Down
118 changes: 99 additions & 19 deletions src/file_compat.h
@@ -1,24 +1,67 @@
#ifndef __FILE_COMPAT_H__
#define __FILE_COMPAT_H__

#include "numpy/npy_3kcompat.h"
#include <Python.h>
#include <stdio.h>
#include "numpy/npy_common.h"
#include "numpy/ndarrayobject.h"
#include "mplutils.h"

#ifdef __cplusplus
extern "C" {
#endif

#if defined(_MSC_VER) && defined(_WIN64) && (_MSC_VER > 1400)
#include <io.h>
#define npy_fseek _fseeki64
#define npy_ftell _ftelli64
#define npy_lseek _lseeki64
#define mpl_off_t npy_int64

#if NPY_SIZEOF_INT == 8
#define MPL_OFF_T_PYFMT "i"
#elif NPY_SIZEOF_LONG == 8
#define MPL_OFF_T_PYFMT "l"
#elif NPY_SIZEOF_LONGLONG == 8
#define MPL_OFF_T_PYFMT "L"
#else
#error Unsupported size for type off_t
#endif
#else
#define npy_fseek fseek
#define npy_ftell ftell
#define npy_lseek lseek
#define mpl_off_t off_t

#if NPY_SIZEOF_INT == NPY_SIZEOF_SHORT
#define MPL_OFF_T_PYFMT "h"
#elif NPY_SIZEOF_INT == NPY_SIZEOF_INT
#define MPL_OFF_T_PYFMT "i"
#elif NPY_SIZEOF_INT == NPY_SIZEOF_LONG
#define MPL_OFF_T_PYFMT "l"
#elif NPY_SIZEOF_INT == NPY_SIZEOF_LONGLONG
#define MPL_OFF_T_PYFMT "L"
#else
#error Unsupported size for type off_t
#endif
#endif

#if NPY_API_VERSION < 0x4 /* corresponds to Numpy 1.5 */
/*
* PyFile_* compatibility
*/
#if defined(NPY_PY3K)
#if PY3K

/*
* Get a FILE* handle to the file represented by the Python object
*/
static NPY_INLINE FILE*
npy_PyFile_Dup(PyObject *file, char *mode)
mpl_PyFile_Dup(PyObject *file, char *mode, mpl_off_t *orig_pos)
{
int fd, fd2;
PyObject *ret, *os;
Py_ssize_t pos;
mpl_off_t pos;
FILE *handle;

/* Flush first to ensure things end up in the file in the correct order */
ret = PyObject_CallMethod(file, "flush", "");
if (ret == NULL) {
Expand All @@ -29,6 +72,9 @@ npy_PyFile_Dup(PyObject *file, char *mode)
if (fd == -1) {
return NULL;
}

/* The handle needs to be dup'd because we have to call fclose
at the end */
os = PyImport_ImportModule("os");
if (os == NULL) {
return NULL;
Expand All @@ -40,6 +86,8 @@ npy_PyFile_Dup(PyObject *file, char *mode)
}
fd2 = PyNumber_AsSsize_t(ret, NULL);
Py_DECREF(ret);

/* Convert to FILE* handle */
#ifdef _WIN32
handle = _fdopen(fd2, mode);
#else
Expand All @@ -49,6 +97,15 @@ npy_PyFile_Dup(PyObject *file, char *mode)
PyErr_SetString(PyExc_IOError,
"Getting a FILE* from a Python file object failed");
}

/* Record the original raw file handle position */
*orig_pos = npy_ftell(handle);
if (*orig_pos == -1) {
PyErr_SetString(PyExc_IOError, "obtaining file position failed");
return NULL;
}

/* Seek raw handle to the Python-side position */
ret = PyObject_CallMethod(file, "tell", "");
if (ret == NULL) {
fclose(handle);
Expand All @@ -60,22 +117,46 @@ npy_PyFile_Dup(PyObject *file, char *mode)
fclose(handle);
return NULL;
}
npy_fseek(handle, pos, SEEK_SET);
if (npy_fseek(handle, pos, SEEK_SET) == -1) {
PyErr_SetString(PyExc_IOError, "seeking file failed");
return NULL;
}
return handle;
}

/*
* Close the dup-ed file handle, and seek the Python one to the current position
*/
static NPY_INLINE int
npy_PyFile_DupClose(PyObject *file, FILE* handle)
mpl_PyFile_DupClose(PyObject *file, FILE* handle, mpl_off_t orig_pos)
{
int fd;
PyObject *ret;
Py_ssize_t position;
mpl_off_t position;

position = npy_ftell(handle);

/* Close the FILE* handle */
fclose(handle);

ret = PyObject_CallMethod(file, "seek", NPY_SSIZE_T_PYFMT "i", position, 0);
/* Restore original file handle position, in order to not confuse
Python-side data structures */
fd = PyObject_AsFileDescriptor(file);
if (fd == -1) {
return -1;
}
if (npy_lseek(fd, orig_pos, SEEK_SET) == -1) {
PyErr_SetString(PyExc_IOError, "seeking file failed");
return -1;
}

if (position == -1) {
PyErr_SetString(PyExc_IOError, "obtaining file position failed");
return -1;
}

/* Seek Python-side handle to the FILE* handle position */
ret = PyObject_CallMethod(file, "seek", MPL_OFF_T_PYFMT "i", position, 0);
if (ret == NULL) {
return -1;
}
Expand All @@ -84,7 +165,7 @@ npy_PyFile_DupClose(PyObject *file, FILE* handle)
}

static NPY_INLINE int
npy_PyFile_Check(PyObject *file)
mpl_PyFile_Check(PyObject *file)
{
int fd;
fd = PyObject_AsFileDescriptor(file);
Expand All @@ -97,13 +178,14 @@ npy_PyFile_Check(PyObject *file)

#else

#define npy_PyFile_Dup(file, mode) PyFile_AsFile(file)
#define npy_PyFile_DupClose(file, handle) (NULL)
#define mpl_PyFile_Dup(file, mode, orig_pos_p) PyFile_AsFile(file)
#define mpl_PyFile_DupClose(file, handle, orig_pos) (0)
#define mpl_PyFile_Check PyFile_Check

#endif

static NPY_INLINE PyObject*
npy_PyFile_OpenFile(PyObject *filename, const char *mode)
mpl_PyFile_OpenFile(PyObject *filename, const char *mode)
{
PyObject *open;
open = PyDict_GetItemString(PyEval_GetBuiltins(), "open");
Expand All @@ -113,12 +195,8 @@ npy_PyFile_OpenFile(PyObject *filename, const char *mode)
return PyObject_CallFunction(open, "Os", filename, mode);
}

#endif /* NPY_API_VERSION < 0x4 */

#if NPY_API_VERSION < 0x7 /* corresponds to Numpy 1.7 */

static NPY_INLINE int
npy_PyFile_CloseFile(PyObject *file)
mpl_PyFile_CloseFile(PyObject *file)
{
PyObject *ret;

Expand All @@ -130,6 +208,8 @@ npy_PyFile_CloseFile(PyObject *file)
return 0;
}

#endif /* NPY_API_VERSION < 0x7 */
#ifdef __cplusplus
}
#endif

#endif /* ifndef __FILE_COMPAT_H__ */