Skip to content

Commit c224269

Browse files
Minor tweaks of BasicIo.mmap()
1 parent cfc7f4e commit c224269

File tree

5 files changed

+100
-123
lines changed

5 files changed

+100
-123
lines changed

USAGE.rst

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -372,15 +372,7 @@ In some cases this includes writing to the data.
372372
buf = thumb.copy()
373373
thumb_im = PIL.Image.open(io.BytesIO(buf.data()))
374374
375-
In python-exiv2 before v0.15.0 the memory block is converted to an object with a buffer interface.
376-
A Python memoryview_ can be used to access the data without copying.
377-
(Converting to bytes_ would make a copy of the data, which we don't usually want.)
378-
379-
Warning: segmentation faults
380-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
381-
382-
Note that the memory block must not be deleted or resized while the memoryview exists.
383-
Doing so will invalidate the memoryview and may cause a segmentation fault:
375+
Since version 0.18.0 python-exiv2 releases the memoryview (when the memory block is resized or deleted) to prevent problems such as segmentation faults:
384376

385377
.. code:: python
386378
@@ -390,24 +382,10 @@ Doing so will invalidate the memoryview and may cause a segmentation fault:
390382
b'fred'
391383
>>> del buf
392384
>>> print(bytes(data))
393-
b'en_G'
394-
395-
Since version 0.18.0 python-exiv2 releases the memoryview (when the memory block is resized) to prevent problems:
396-
397-
.. code:: python
398-
399-
>>> buf = exiv2.DataBuf(b'fred')
400-
>>> data = buf.data()
401-
>>> print(bytes(data))
402-
b'fred'
403-
>>> buf.alloc(128)
404-
>>> print(bytes(data))
405385
Traceback (most recent call last):
406386
File "<stdin>", line 1, in <module>
407387
ValueError: operation forbidden on released memoryview object
408388
409-
Unfortunately I haven't been able to make this work for memory block deletion.
410-
411389
Buffer interface
412390
----------------
413391

src/interface/basicio.i

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -133,17 +133,8 @@ OUTPUT_BUFFER_RW(Exiv2::byte* buf, size_t rcount)
133133
%ignore Exiv2::BasicIo::mmap();
134134

135135
// Convert mmap() result to a Python memoryview, assumes arg2 = isWriteable
136-
// The callback is used to call munmap when the memoryview is deleted
137-
RETURN_VIEW_CB(Exiv2::byte* mmap, $1 ? arg1->size() : 0,
138-
arg2 ? PyBUF_WRITE : PyBUF_READ,
139-
PyObject_GetAttrString(self, "_release"),)
140-
141-
// Define callback function
142-
%extend Exiv2::BasicIo {
143-
void _release(PyObject* ref) {
144-
self->munmap();
145-
};
146-
}
136+
RETURN_VIEW(Exiv2::byte* mmap, $1 ? arg1->size() : 0,
137+
arg2 ? PyBUF_WRITE : PyBUF_READ,)
147138

148139
// Release memoryviews when mmap or data is called
149140
%typemap(check, fragment="memoryview_funcs") bool isWriteable {
@@ -152,21 +143,25 @@ RETURN_VIEW_CB(Exiv2::byte* mmap, $1 ? arg1->size() : 0,
152143

153144
// Release memoryviews when some other functions are called
154145
%typemap(ret, fragment="memoryview_funcs")
155-
(int close), (int munmap), (long write), (size_t write) %{
146+
(int close), (int munmap), (long write), (size_t write),
147+
(void _release) %{
156148
release_views(self);
157149
%}
158150

159151
// Add data() method for easy access
152+
// The callback is used to call munmap when the memoryview is deleted
160153
RETURN_VIEW_CB(Exiv2::byte* data, $1 ? arg1->size() : 0,
161154
arg2 ? PyBUF_WRITE : PyBUF_READ,
162155
PyObject_GetAttrString(self, "_release"),)
163156
%extend Exiv2::BasicIo {
164157
Exiv2::byte* data(bool isWriteable) {
165-
if (!self->isopen())
166-
self->open();
167-
self->munmap();
158+
self->open();
168159
return self->mmap(isWriteable);
169160
};
161+
void _release(PyObject* ref) {
162+
self->munmap();
163+
self->close();
164+
};
170165
}
171166

172167
// Enable len(Exiv2::BasicIo)

src/swig-0_27_7/basicio_wrap.cxx

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4874,15 +4874,14 @@ SWIGINTERN char const *Exiv2_BasicIo_ioType(Exiv2::BasicIo *self){
48744874
}
48754875
return "unknown";
48764876
}
4877-
SWIGINTERN void Exiv2_BasicIo__release(Exiv2::BasicIo *self,PyObject *ref){
4878-
self->munmap();
4879-
}
48804877
SWIGINTERN Exiv2::byte *Exiv2_BasicIo_data(Exiv2::BasicIo *self,bool isWriteable){
4881-
if (!self->isopen())
4882-
self->open();
4883-
self->munmap();
4878+
self->open();
48844879
return self->mmap(isWriteable);
48854880
}
4881+
SWIGINTERN void Exiv2_BasicIo__release(Exiv2::BasicIo *self,PyObject *ref){
4882+
self->munmap();
4883+
self->close();
4884+
}
48864885
#ifdef __cplusplus
48874886
extern "C" {
48884887
#endif
@@ -5510,7 +5509,7 @@ SWIGINTERN PyObject *_wrap_BasicIo_mmap(PyObject *self, PyObject *args) {
55105509
if (!resultobj)
55115510
SWIG_fail;
55125511
// Store a weak ref to the new memoryview
5513-
if (store_view(self, resultobj, PyObject_GetAttrString(self, "_release")))
5512+
if (store_view(self, resultobj, NULL))
55145513
SWIG_fail;
55155514

55165515
return resultobj;
@@ -5727,26 +5726,41 @@ SWIGINTERN PyObject *_wrap_BasicIo_ioType(PyObject *self, PyObject *args) {
57275726
}
57285727

57295728

5730-
SWIGINTERN PyObject *_wrap_BasicIo__release(PyObject *self, PyObject *args) {
5729+
SWIGINTERN PyObject *_wrap_BasicIo_data(PyObject *self, PyObject *args) {
57315730
PyObject *resultobj = 0;
57325731
Exiv2::BasicIo *arg1 = (Exiv2::BasicIo *) 0 ;
5733-
PyObject *arg2 = (PyObject *) 0 ;
5732+
bool arg2 ;
57345733
void *argp1 = 0 ;
57355734
int res1 = 0 ;
5735+
bool val2 ;
5736+
int ecode2 = 0 ;
57365737
PyObject * obj1 = 0 ;
5738+
Exiv2::byte *result = 0 ;
57375739

5738-
if (!PyArg_UnpackTuple(args, "BasicIo__release", 1, 1, &obj1)) SWIG_fail;
5740+
{
5741+
arg2 = false;
5742+
}
5743+
if (!PyArg_UnpackTuple(args, "BasicIo_data", 0, 1, &obj1)) SWIG_fail;
57395744
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_Exiv2__BasicIo, 0 | 0 );
57405745
if (!SWIG_IsOK(res1)) {
5741-
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "BasicIo__release" "', argument " "1"" of type '" "Exiv2::BasicIo *""'");
5746+
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "BasicIo_data" "', argument " "1"" of type '" "Exiv2::BasicIo *""'");
57425747
}
57435748
arg1 = reinterpret_cast< Exiv2::BasicIo * >(argp1);
5744-
arg2 = obj1;
5749+
if (obj1) {
5750+
ecode2 = SWIG_AsVal_bool(obj1, &val2);
5751+
if (!SWIG_IsOK(ecode2)) {
5752+
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "BasicIo_data" "', argument " "2"" of type '" "bool""'");
5753+
}
5754+
arg2 = static_cast< bool >(val2);
5755+
}
5756+
{
5757+
release_views(self);
5758+
}
57455759
{
57465760
try {
57475761
{
57485762
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
5749-
Exiv2_BasicIo__release(arg1,arg2);
5763+
result = (Exiv2::byte *)Exiv2_BasicIo_data(arg1,arg2);
57505764
SWIG_PYTHON_THREAD_END_ALLOW;
57515765
}
57525766
}
@@ -5755,48 +5769,40 @@ SWIGINTERN PyObject *_wrap_BasicIo__release(PyObject *self, PyObject *args) {
57555769
SWIG_fail;
57565770
}
57575771
}
5758-
resultobj = SWIG_Py_Void();
5772+
5773+
resultobj = PyMemoryView_FromMemory((char*)result, result ? arg1->size() : 0, arg2 ? PyBUF_WRITE : PyBUF_READ);
5774+
if (!resultobj)
5775+
SWIG_fail;
5776+
// Store a weak ref to the new memoryview
5777+
if (store_view(self, resultobj, PyObject_GetAttrString(self, "_release")))
5778+
SWIG_fail;
5779+
57595780
return resultobj;
57605781
fail:
57615782
return NULL;
57625783
}
57635784

57645785

5765-
SWIGINTERN PyObject *_wrap_BasicIo_data(PyObject *self, PyObject *args) {
5786+
SWIGINTERN PyObject *_wrap_BasicIo__release(PyObject *self, PyObject *args) {
57665787
PyObject *resultobj = 0;
57675788
Exiv2::BasicIo *arg1 = (Exiv2::BasicIo *) 0 ;
5768-
bool arg2 ;
5789+
PyObject *arg2 = (PyObject *) 0 ;
57695790
void *argp1 = 0 ;
57705791
int res1 = 0 ;
5771-
bool val2 ;
5772-
int ecode2 = 0 ;
57735792
PyObject * obj1 = 0 ;
5774-
Exiv2::byte *result = 0 ;
57755793

5776-
{
5777-
arg2 = false;
5778-
}
5779-
if (!PyArg_UnpackTuple(args, "BasicIo_data", 0, 1, &obj1)) SWIG_fail;
5794+
if (!PyArg_UnpackTuple(args, "BasicIo__release", 1, 1, &obj1)) SWIG_fail;
57805795
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_Exiv2__BasicIo, 0 | 0 );
57815796
if (!SWIG_IsOK(res1)) {
5782-
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "BasicIo_data" "', argument " "1"" of type '" "Exiv2::BasicIo *""'");
5797+
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "BasicIo__release" "', argument " "1"" of type '" "Exiv2::BasicIo *""'");
57835798
}
57845799
arg1 = reinterpret_cast< Exiv2::BasicIo * >(argp1);
5785-
if (obj1) {
5786-
ecode2 = SWIG_AsVal_bool(obj1, &val2);
5787-
if (!SWIG_IsOK(ecode2)) {
5788-
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "BasicIo_data" "', argument " "2"" of type '" "bool""'");
5789-
}
5790-
arg2 = static_cast< bool >(val2);
5791-
}
5792-
{
5793-
release_views(self);
5794-
}
5800+
arg2 = obj1;
57955801
{
57965802
try {
57975803
{
57985804
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
5799-
result = (Exiv2::byte *)Exiv2_BasicIo_data(arg1,arg2);
5805+
Exiv2_BasicIo__release(arg1,arg2);
58005806
SWIG_PYTHON_THREAD_END_ALLOW;
58015807
}
58025808
}
@@ -5805,13 +5811,9 @@ SWIGINTERN PyObject *_wrap_BasicIo_data(PyObject *self, PyObject *args) {
58055811
SWIG_fail;
58065812
}
58075813
}
5814+
resultobj = SWIG_Py_Void();
58085815

5809-
resultobj = PyMemoryView_FromMemory((char*)result, result ? arg1->size() : 0, arg2 ? PyBUF_WRITE : PyBUF_READ);
5810-
if (!resultobj)
5811-
SWIG_fail;
5812-
// Store a weak ref to the new memoryview
5813-
if (store_view(self, resultobj, PyObject_GetAttrString(self, "_release")))
5814-
SWIG_fail;
5816+
release_views(self);
58155817

58165818
return resultobj;
58175819
fail:
@@ -6033,8 +6035,8 @@ SWIGINTERN PyMethodDef SwigPyBuiltin__Exiv2__BasicIo_methods[] = {
60336035
":rtype: str\n"
60346036
":return: A class name such as \"FileIo\".\n"
60356037
"" },
6036-
{ "_release", _wrap_BasicIo__release, METH_VARARGS, "" },
60376038
{ "data", _wrap_BasicIo_data, METH_VARARGS, "" },
6039+
{ "_release", _wrap_BasicIo__release, METH_VARARGS, "" },
60386040
{ NULL, NULL, 0, NULL } /* Sentinel */
60396041
};
60406042

0 commit comments

Comments
 (0)