[pygobject] Avoid copying bytearrays from Python to C when transfer nothing
- From: Garrett Regier <gregier src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Avoid copying bytearrays from Python to C when transfer nothing
- Date: Mon, 16 Feb 2015 19:40:29 +0000 (UTC)
commit 60de632153a693fb2b0f2ce26208c6ff668bdf4d
Author: Garrett Regier <garrett regier riftio com>
Date: Tue Jan 27 10:39:53 2015 -0800
Avoid copying bytearrays from Python to C when transfer nothing
https://bugzilla.gnome.org/show_bug.cgi?id=743278
gi/pygi-array.c | 23 +++++++++++++++++++----
tests/test_gi.py | 14 +++++++++++++-
2 files changed, 32 insertions(+), 5 deletions(-)
---
diff --git a/gi/pygi-array.c b/gi/pygi-array.c
index e2598cd..121992b 100644
--- a/gi/pygi-array.c
+++ b/gi/pygi-array.c
@@ -191,6 +191,7 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
GArray *array_ = NULL;
PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
+ GITransfer cleanup_transfer = arg_cache->transfer;
if (py_arg == Py_None) {
@@ -234,7 +235,21 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8 &&
PYGLIB_PyBytes_Check (py_arg)) {
- memcpy(array_->data, PYGLIB_PyBytes_AsString (py_arg), length);
+ gchar *data = PYGLIB_PyBytes_AsString (py_arg);
+
+ /* Avoid making a copy if the data
+ * is not transferred to the C function
+ * and cannot not be modified by it.
+ */
+ if (array_cache->array_type == GI_ARRAY_TYPE_C &&
+ arg_cache->transfer == GI_TRANSFER_NOTHING &&
+ !array_cache->is_zero_terminated) {
+ g_free (array_->data);
+ array_->data = data;
+ cleanup_transfer = GI_TRANSFER_EVERYTHING;
+ } else {
+ memcpy (array_->data, data, length);
+ }
array_->len = length;
if (array_cache->is_zero_terminated) {
/* If array_ has been created with zero_termination, space for the
@@ -385,7 +400,7 @@ array_success:
*/
arg->v_pointer = array_->data;
- if (arg_cache->transfer == GI_TRANSFER_EVERYTHING) {
+ if (cleanup_transfer == GI_TRANSFER_EVERYTHING) {
g_array_free (array_, FALSE);
*cleanup_data = NULL;
} else {
@@ -394,10 +409,10 @@ array_success:
} else {
arg->v_pointer = array_;
- if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
+ if (cleanup_transfer == GI_TRANSFER_NOTHING) {
/* Free everything in cleanup. */
*cleanup_data = array_;
- } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
+ } else if (cleanup_transfer == GI_TRANSFER_CONTAINER) {
/* Make a shallow copy so we can free the elements later in cleanup
* because it is possible invoke will free the list before our cleanup. */
*cleanup_data = is_ptr_array ?
diff --git a/tests/test_gi.py b/tests/test_gi.py
index 31b31f5..f85d60f 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -1089,7 +1089,19 @@ class TestGByteArray(unittest.TestCase):
self.assertEqual(b'\x001\xFF3', GIMarshallingTests.bytearray_full_return())
def test_bytearray_none_in(self):
- GIMarshallingTests.bytearray_none_in(b'\x00\x31\xFF\x33')
+ b = b'\x00\x31\xFF\x33'
+ ba = GLib.ByteArray.new_take(b)
+
+ # b should always have the same value even
+ # though the generated GByteArray is being modified
+ GIMarshallingTests.bytearray_none_in(b)
+ GIMarshallingTests.bytearray_none_in(b)
+
+ # The GByteArray is just a bytes
+ # thus it will not reflect any changes
+ GIMarshallingTests.bytearray_none_in(ba)
+ GIMarshallingTests.bytearray_none_in(ba)
+ #self.assertEqual(ba, b'\x00\x31\x00\x33')
class TestGList(unittest.TestCase):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]