-
Notifications
You must be signed in to change notification settings - Fork 2
Source Generation
Classes inheriting IOsuNativeObject<T> represent a native object, and higher-level methods in marked with the OsuNativeFunction attribute generate a corresponding native function (UnmanagedCallersOnly).
These methods must be be static and return an ErrorCode (see Error Handling). This allows low-level error-handling logic to be universally applied to all native functions, and writing the actual logic of the function becomes more straight-forward.
Example:
source
public partial class RulesetObject : IOsuNativeObject<Ruleset>
{
[OsuNativeFunction]
private static ErrorCode CreateFromId(int rulesetId, NativeRuleset* rulesetPtr)
{ ... }
}generated
public partial class BeatmapObject
{
[CompilerGenerated]
[UnmanagedCallersOnly(EntryPoint = "Ruleset_CreateFromId", CallConvs = [typeof(CallConvCdecl)])]
private static ErrorCode Ruleset_CreateFromId(int rulesetId, global::osu.Native.Structures.NativeRuleset* rulesetPtr)
{
ErrorHandler.SetLastMessage(null);
try
{
return osu.Native.Objects.RulesetObject.CreateFromId(rulesetId, rulesetPtr);
}
catch (Exception ex)
{
return ErrorHandler.HandleException(ex);
}
}
}The name of the native functions is determined by the method name and class name, trimming off an optional "Object" suffix.
Example: BeatmapObject and GetTitle -> Beatmap_GetTitle
Additionally, a native Destroy function is generated for the object, allowing the caller to destroy the managed object of the handle.
A ManagedObjectHandle<T> represents a reference to a managed object of the type T inside osu-native, and is natively depicted by an unsigned 32-bit integer. It is used for the caller to refer to managed objects inside osu-native.
internal struct ManagedObjectHandle<T>
{
public uint Id;
}An id of 0 represents a "null"-handle, and represent the absence of an object (the managed equivalent would be null).