You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: Ensure progress callback live long enough to be used (#205)
* fix: Init
* fix: Rename var ref
* Update context.test.cpp
* fix: Test clean up to use new APIs and no warn
* fix: Update docs
* fix: Build and deprecations
* fix: Clean up
-**Non-copyable, moveable**: `Context` can be moved but not copied. After moving, `is_valid()` returns `false` on the source
69
-
-**Used at construction**: `Reader` and `Builder`copy configuration from the context at construction time. The `Context` doesn't need to outlive them
70
-
-**Reusable**: Use the same `Context` to create multiple readers and builders
69
+
-**Pass as `shared_ptr`**: `Reader` and `Builder`retain a shared reference to the context, keeping it alive for their lifetime. This is required when using progress callbacks — without it, the callback can fire after the context is destroyed, causing a crash
70
+
-**Reusable**: Use the same `shared_ptr<Context>` to create multiple readers and builders
71
71
72
72
```cpp
73
-
c2pa::Contextcontext(settings);
73
+
auto context = std::make_shared<c2pa::Context>(settings);
74
74
75
75
// All three use the same configuration
76
76
c2pa::Builder builder1(context, manifest1);
77
77
c2pa::Builder builder2(context, manifest2);
78
78
c2pa::Reader reader(context, "image.jpg");
79
79
80
-
// Context can go out of scope, readers/builders still work
80
+
// context shared_ptr can go out of scope — reader/builder each hold a reference
81
81
```
82
82
83
83
### Settings format
@@ -179,15 +179,15 @@ Use `ContextBuilder::with_progress_callback` to attach a callback before buildin
179
179
180
180
std::atomic<int> phase_count{0};
181
181
182
-
auto context = c2pa::Context::ContextBuilder()
182
+
auto context = std::make_shared<c2pa::Context>(c2pa::Context::ContextBuilder()
`Reader` uses `Context` to control validation, trust configuration, network access, and performance.
385
385
386
386
> [!IMPORTANT]
387
-
> `Context`is used only at construction. `Reader`copies the configuration it needs internally, so the `Context` doesn't need to outlive the `Reader`.
387
+
> Pass `Context`as a `shared_ptr`. `Reader`retains a shared reference, keeping the context alive for its lifetime. This is required when using progress callbacks.
388
388
389
389
### Reading from a file
390
390
391
391
```cpp
392
-
c2pa::Contextcontext(R"({
392
+
auto context = std::make_shared<c2pa::Context>(R"({
`Builder` uses `Context` to control manifest creation, signing, thumbnails, and more.
415
415
416
416
> [!IMPORTANT]
417
-
> The`Context`is used only when constructing the `Builder`. It copies the configuration internally, so the `Context` doesn't need to outlive the `Builder`.
417
+
> Pass`Context`as a `shared_ptr`. `Builder` retains a shared reference, keeping the context alive for its lifetime. This is required when using progress callbacks.
418
418
419
419
```cpp
420
-
c2pa::Contextcontext(R"({
420
+
auto context = std::make_shared<c2pa::Context>(R"({
421
421
"version": 1,
422
422
"builder": {
423
423
"claim_generator_info": {"name": "My App", "version": "1.0"},
If you need default SDK behavior and have no custom settings, `c2pa::Context context;` with no arguments is sufficient.
951
+
### Using shared_ptr instead of reference for Reader and Builder
950
952
951
-
#### About IContextProvider
953
+
The `IContextProvider&` reference overloads are deprecated because they do not extend the lifetime of the context. If the context is destroyed while a `Reader` or `Builder` has a progress callback registered, the callback fires against freed memory, causing a crash.
952
954
953
-
The deprecation warnings reference `IContextProvider` in their suggested fix (e.g., "Use Reader(IContextProvider& context, ...)"). `IContextProvider` is the interface that `Reader` and `Builder` constructors accept. `Context` is the SDK's built-in implementation of this interface.
955
+
**Deprecated:**
954
956
955
-
When the deprecation warning says "Use Reader(IContextProvider& context, ...)", passing a `Context` object satisfies that parameter.
957
+
```cpp
958
+
c2pa::Context context;
959
+
c2pa::Reader reader(context, "image.jpg"); // reference — context not kept alive
960
+
c2pa::Builder builder(context, manifest_json); // reference — context not kept alive
961
+
c2pa::Reader::from_asset(context, "image.jpg"); // reference — context not kept alive
962
+
```
956
963
957
-
External libraries can also implement `IContextProvider` to provide their own context objects (for example, wrapping a platform-specific configuration system). The interface is minimal: any class that can produce a valid `C2paContext*` pointer and report its validity can serve as a context provider. This becomes relevant when building integrations that need to manage context lifetime or initialization differently than the SDK's `Context` class does.
964
+
**With shared_ptr:**
965
+
966
+
```cpp
967
+
auto context = std::make_shared<c2pa::Context>();
968
+
c2pa::Reader reader(context, "image.jpg");
969
+
c2pa::Builder builder(context, manifest_json);
970
+
c2pa::Reader::from_asset(context, "image.jpg");
971
+
```
972
+
973
+
The `shared_ptr` overloads accept any `shared_ptr<IContextProvider>`, so custom `IContextProvider` implementations work the same way, wrap them in a `shared_ptr` before passing.
974
+
975
+
#### About IContextProvider
976
+
977
+
`IContextProvider` is the interface that `Reader` and `Builder` constructors accept. `Context` is the SDK's built-in implementation. The deprecation warnings reference it in the suggested replacement (e.g., `"Use Reader(std::shared_ptr<IContextProvider>, ...)`").
978
+
979
+
External libraries can implement `IContextProvider` to supply their own context objects. The interface requires a valid `C2paContext*` pointer and an `is_valid()` check. Wrap your implementation in a `shared_ptr` when passing to `Reader` or `Builder`.
958
980
959
981
### Builder::sign overloads
960
982
@@ -982,10 +1004,10 @@ If a signer is configured in the `Context` (through settings JSON or `ContextBui
0 commit comments