From 8dd6568d429984775aeacfdf46da73d05386f6c2 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Fri, 19 Sep 2025 20:35:59 -0700 Subject: [PATCH 1/4] fix: 1 --- src/c2pa/c2pa.py | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/c2pa/c2pa.py b/src/c2pa/c2pa.py index 7d920e6..64771fa 100644 --- a/src/c2pa/c2pa.py +++ b/src/c2pa/c2pa.py @@ -336,6 +336,19 @@ def _setup_function(func, argtypes, restype=None): None ) +# Add dummy context functions +_setup_function( + _lib.c2pa_create_dummy_context, + [], + ctypes.POINTER(StreamContext) +) + +_setup_function( + _lib.c2pa_free_dummy_context, + [ctypes.POINTER(StreamContext)], + None +) + # Set up function prototypes not attached to an API object _setup_function(_lib.c2pa_version, [], ctypes.c_void_p) _setup_function(_lib.c2pa_error, [], ctypes.c_void_p) @@ -1123,9 +1136,12 @@ def flush_callback(ctx): self._write_cb = WriteCallback(write_callback) self._flush_cb = FlushCallback(flush_callback) + # Create a dummy context since Python callbacks don't use it + self._dummy_context = _lib.c2pa_create_dummy_context() + # Create the stream self._stream = _lib.c2pa_create_stream( - None, # context + self._dummy_context, # context self._read_cb, self._seek_cb, self._write_cb, @@ -1170,6 +1186,15 @@ def __del__(self): self._stream = None self._closed = True self._initialized = False + + # Clean up dummy context + if hasattr(self, '_dummy_context') and self._dummy_context: + try: + _lib.c2pa_free_dummy_context(self._dummy_context) + except Exception: + pass + finally: + self._dummy_context = None except Exception: # Destructors must not raise exceptions pass @@ -1200,6 +1225,17 @@ def close(self): finally: self._stream = None + # Clean up dummy context + if hasattr(self, '_dummy_context') and self._dummy_context: + try: + _lib.c2pa_free_dummy_context(self._dummy_context) + except Exception as e: + logger.error( + Stream._ERROR_MESSAGES['callback_error'].format( + 'dummy_context', str(e))) + finally: + self._dummy_context = None + # Clean up callbacks for attr in ['_read_cb', '_seek_cb', '_write_cb', '_flush_cb']: if hasattr(self, attr): From 4979476d43d32ecaa5ecd87c17e99a5964af74f0 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Fri, 19 Sep 2025 20:59:19 -0700 Subject: [PATCH 2/4] fix: Update c2pa.py code --- src/c2pa/c2pa.py | 37 +++---------------------------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/src/c2pa/c2pa.py b/src/c2pa/c2pa.py index 64771fa..3882a10 100644 --- a/src/c2pa/c2pa.py +++ b/src/c2pa/c2pa.py @@ -336,19 +336,6 @@ def _setup_function(func, argtypes, restype=None): None ) -# Add dummy context functions -_setup_function( - _lib.c2pa_create_dummy_context, - [], - ctypes.POINTER(StreamContext) -) - -_setup_function( - _lib.c2pa_free_dummy_context, - [ctypes.POINTER(StreamContext)], - None -) - # Set up function prototypes not attached to an API object _setup_function(_lib.c2pa_version, [], ctypes.c_void_p) _setup_function(_lib.c2pa_error, [], ctypes.c_void_p) @@ -1137,11 +1124,12 @@ def flush_callback(ctx): self._flush_cb = FlushCallback(flush_callback) # Create a dummy context since Python callbacks don't use it - self._dummy_context = _lib.c2pa_create_dummy_context() + # We create a small buffer and cast it to a StreamContext pointer + self._dummy_context = ctypes.create_string_buffer(1) # Create a 1-byte buffer # Create the stream self._stream = _lib.c2pa_create_stream( - self._dummy_context, # context + ctypes.cast(self._dummy_context, ctypes.POINTER(StreamContext)), # context self._read_cb, self._seek_cb, self._write_cb, @@ -1186,15 +1174,6 @@ def __del__(self): self._stream = None self._closed = True self._initialized = False - - # Clean up dummy context - if hasattr(self, '_dummy_context') and self._dummy_context: - try: - _lib.c2pa_free_dummy_context(self._dummy_context) - except Exception: - pass - finally: - self._dummy_context = None except Exception: # Destructors must not raise exceptions pass @@ -1225,16 +1204,6 @@ def close(self): finally: self._stream = None - # Clean up dummy context - if hasattr(self, '_dummy_context') and self._dummy_context: - try: - _lib.c2pa_free_dummy_context(self._dummy_context) - except Exception as e: - logger.error( - Stream._ERROR_MESSAGES['callback_error'].format( - 'dummy_context', str(e))) - finally: - self._dummy_context = None # Clean up callbacks for attr in ['_read_cb', '_seek_cb', '_write_cb', '_flush_cb']: From 60c0bac166e8abcabab0fdea14b446f538763e07 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Sat, 20 Sep 2025 20:44:55 -0700 Subject: [PATCH 3/4] fix: Renamings --- src/c2pa/c2pa.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/c2pa/c2pa.py b/src/c2pa/c2pa.py index 3882a10..b63afaa 100644 --- a/src/c2pa/c2pa.py +++ b/src/c2pa/c2pa.py @@ -1123,13 +1123,14 @@ def flush_callback(ctx): self._write_cb = WriteCallback(write_callback) self._flush_cb = FlushCallback(flush_callback) - # Create a dummy context since Python callbacks don't use it - # We create a small buffer and cast it to a StreamContext pointer - self._dummy_context = ctypes.create_string_buffer(1) # Create a 1-byte buffer - + # Create a (placeholder) context we don't actually use the context, + # but we need having a valid context pointer. Therefore, we create + # a small buffer and cast it to a StreamContext pointer + self._placeholder_context = ctypes.create_string_buffer(1) + # Create the stream self._stream = _lib.c2pa_create_stream( - ctypes.cast(self._dummy_context, ctypes.POINTER(StreamContext)), # context + ctypes.cast(self._placeholder_context, ctypes.POINTER(StreamContext)), # context self._read_cb, self._seek_cb, self._write_cb, From 31f94b574e4acae0ecc8884b47fa3c6380cafa26 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Sat, 20 Sep 2025 20:48:41 -0700 Subject: [PATCH 4/4] fix: Format --- src/c2pa/c2pa.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/c2pa/c2pa.py b/src/c2pa/c2pa.py index b63afaa..c8524bc 100644 --- a/src/c2pa/c2pa.py +++ b/src/c2pa/c2pa.py @@ -1123,14 +1123,14 @@ def flush_callback(ctx): self._write_cb = WriteCallback(write_callback) self._flush_cb = FlushCallback(flush_callback) - # Create a (placeholder) context we don't actually use the context, + # Create a placeholder context as we don't actually use the context, # but we need having a valid context pointer. Therefore, we create # a small buffer and cast it to a StreamContext pointer - self._placeholder_context = ctypes.create_string_buffer(1) + self._context = ctypes.create_string_buffer(1) # Create the stream self._stream = _lib.c2pa_create_stream( - ctypes.cast(self._placeholder_context, ctypes.POINTER(StreamContext)), # context + ctypes.cast(self._context, ctypes.POINTER(StreamContext)), self._read_cb, self._seek_cb, self._write_cb, @@ -1205,7 +1205,6 @@ def close(self): finally: self._stream = None - # Clean up callbacks for attr in ['_read_cb', '_seek_cb', '_write_cb', '_flush_cb']: if hasattr(self, attr):