Skip to content

feat: add BinaryView.AddAnalysisCompletionEvent (Python parity)#31

Merged
tinysec merged 1 commit into
masterfrom
fix/add-analysis-completion-event
Jul 8, 2026
Merged

feat: add BinaryView.AddAnalysisCompletionEvent (Python parity)#31
tinysec merged 1 commit into
masterfrom
fix/add-analysis-completion-event

Conversation

@tinysec

@tinysec tinysec commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Summary

Closes a HIGH-severity parity gap: the binding declared BNAddAnalysisCompletionEvent but never exposed it, so managed callers had no way to be notified when an analysis pass completes — essential for headless automation (the primary use case for a C# binding).

Mirrors Python BinaryView.add_analysis_completion_event (binaryview.py:8068).

Changes

  • BinaryView.AddAnalysisCompletionEvent(Action) — registers a callback that fires once when the next analysis pass completes.
  • AnalysisCompletionEvent.Create(view, callback) — wraps the user Action into the native void(*)(void*) shape and roots the wrapper delegate on the event instance for its lifetime (same delegate-marshaling pattern as Activity.Create, PR fix: root registered-callback delegates and fix metadata handle ownership #15), so the GC cannot reclaim the function pointer while the core still holds it.
  • AnalysisCompletionEventCallbackDelegate + AnalysisCompletionEventContext (new file Delegate/AnalysisCompletionEventCallbackDelegate.cs) — the native delegate and a no-lambda named-method adapter, matching the repo's existing ActivityActionDelegate.cs structure.

Lifetime contract

The caller must keep the returned AnalysisCompletionEvent alive (e.g. in a field) for as long as the callback should remain armed; disposing or GC-collecting it cancels the event and frees the delegate. This matches the existing Activity model. Documented on the public method.

E2E tests (harness repo, not this repo)

  • AddAnalysisCompletionEventReturnsNonNullEvent
  • CallbackFiresAfterUpdateAnalysisAndWait (sync path)
  • CallbackFiresAfterAsyncUpdateAnalysis (async path — the primary use case)

All 3 pass; full harness regression 49/49.

The C# binding declared the BNAddAnalysisCompletionEvent P/Invoke but
never exposed it: AnalysisCompletionEvent had only an internal handle
ctor and a Cancel() method, and BinaryView had no way to register an
analysis-completion callback. Headless automation therefore could not
be notified when a (possibly async) analysis pass finished.

Mirror Python BinaryView.add_analysis_completion_event
(binaryview.py:8068): add BinaryView.AddAnalysisCompletionEvent(Action)
returning an AnalysisCompletionEvent whose lifetime roots the native
callback delegate (the Activity/PR #15 delegate-marshaling pattern),
so the GC cannot free the function pointer while the core still holds
it. The caller must keep the returned event alive; disposing or
collecting it cancels the event (documented).
@tinysec tinysec merged commit a525ebe into master Jul 8, 2026
1 check passed
@tinysec tinysec deleted the fix/add-analysis-completion-event branch July 8, 2026 16:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant