Repository navigation
Closed
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-System.Runtime.InteropServices
Milestone
Description
Background and motivation
The current ObjectiveCMarshal.CreateReferenceTrackingHandle API does two things:
- Creates a tracking GCHandle
- Returns tagged memory for the object in question.
I'm trying to improve memory usage and simplify code in dotnet/macios, and as part of that I want to store some flags in the tagged memory. These flags must exist before we have a tracking GCHandle (and also after any such handles have been freed), so I think it would make sense to have a separate API to just get the tagged memory, without creating a tracking GCHandle.
API Proposal
namespace System.Runtime.InteropServices.ObjectiveC;
public static class ObjectiveCMarshal
{
/// <summary>
/// Request a pointer to memory tagged for the supplied object.
/// </summary>
/// <param name="obj">The object whose tagged memory to return.</param>
/// <returns>A pointer to memory tagged to the object.</returns>
/// <exception cref="InvalidOperationException">Thrown if the ObjectiveCMarshal API has not been initialized.</exception>
/// <remarks>
/// The Initialize() must be called prior to calling this function.
///
/// The <paramref name="obj"/> must have a type in its hierarchy marked with
/// <see cref="ObjectiveCTrackedTypeAttribute"/>.
///
/// The "Is Referenced" callback passed to <see cref="Initialize" />
/// will be passed the memory returned from this function.
/// The memory it points at is defined by the length in the <see cref="Span{IntPtr}"/> and
/// will be zeroed out. It will be available until <paramref name="obj"/> is collected by the GC.
/// The returned memory can be used for any purpose by the caller of this function and usable
/// during the "Is Referenced" callback.
///
/// Calling this function multiple times with the same <paramref name="obj"/> will
/// return the same tagged memory. It is only guaranteed to be zero initialized on
/// the first call.
///
/// The return value is the same as the tagged memory returned from <see cref="CreateReferenceTrackingHandle" />.
/// </remarks>
public static Span<IntPtr> GetOrCreateTaggedMemory(object obj);
}API Usage
This would be used somewhat like this:
var memory = ObjectiveCMarshal.GetOrCreateTaggedMemory (myObject);
fixed (void *ptr = memory)
((NSObjectData *) ptr)->flags = MyFlag;Alternative Designs
Calling ObjectiveCMarshal.CreateReferenceTrackingHandle and just immediately freeing the GCHandle works fine:
public static Span<IntPtr> GetOrCreateTaggedMemory (object obj)
{
var handle = ObjectiveCMarshal.CreateReferenceTrackingHandle (obj, out var span);
handle.Free ();
return span;
}but this feels rather wasteful.
Risks
None that I can think of.
Metadata
Metadata
Assignees
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-System.Runtime.InteropServices
Type
Projects
- StatusShow more project fieldsNo status
Activity
rolfbjarne commentedon May 22, 2026
CC @AaronRobinsonMSFT
dotnet-policy-service commentedon May 22, 2026
Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.
AaronRobinsonMSFT commentedon May 22, 2026
AaronRobinsonMSFT commentedon May 22, 2026
Oops, sorry. Please ignore #128476 (comment). I was looking at the
JavaMarshalAPI not theObjectiveCMarshalAPI surface area. I don't see aGetContext()on theObjectiveCMarshalclass. This does seem annoying. Let me review this again.AaronRobinsonMSFT commentedon May 22, 2026
@rolfbjarne Okay, this API makes some more sense now that I'm looking at the Objective-C APIs.
My only suggestion would be to update the name to be
public Span<IntPtr> GetOrCreateTaggedMemory(object obj)The implementation would be simple and I don't see any real issues with adding this behavior since it would just be part of the "prestep" for the existing API. No new semantics appear to be introduced in this case. I agree with your documnetation as well keeping all the same invariants for this API as for
CreateReferenceTrackingHandle.Apologies for the initial confusion.
AaronRobinsonMSFT commentedon May 22, 2026
Please update the API with the suggested name and then feel free to mark it with "api-ready-for-review".
AaronRobinsonMSFT commentedon May 22, 2026
@rolfbjarne Airport time is "free" time, objcmarshal-get-or-create-tagged-memory.
[-][API Proposal]: Add ObjectiveCMarshal.GetTaggedMemory[/-][+][API Proposal]: Add ObjectiveCMarshal.GetOrCreateTaggedMemory[/+]AaronRobinsonMSFT commentedon Jun 1, 2026
GetOrCreateReferenceTrackingMemorydue to "TaggedMemory" being new nomenclature that didn't seem necessary.[-][API Proposal]: Add ObjectiveCMarshal.GetOrCreateTaggedMemory[/-][+][API Proposal]: Add API for getting memory for Objective-C object without creating GCHandle[/+][-][API Proposal]: Add API for getting memory for Objective-C object without creating GCHandle[/-][+][API Proposal]: Add API for getting memory for Objective-C object without creating `GCHandle`[/+]Add `ObjectiveCMarshal.GetOrCreateReferenceTrackingMemory` API (#128508)
Add `ObjectiveCMarshal.GetOrCreateReferenceTrackingMemory` API (#128508)