[src] Add a TransientCFString struct. (#19763)
In order to make it easier to pass C-style strings to P/Invokes, we introduced a TransientString struct some time ago. This works quite well, so I implemented the same for CFStrings - a TransientCFString struct - and started using it in a few places. The idea would be to slowly start migrating our codebase to this new pattern. Instead of: var ptr = CFString.CreateNative ("somestring"); try { CallPInvoke (ptr); } finally { CFString.ReleaseNative (ptr); } we'll do: using var ptr = new TransientCFString ("somestring"); CallPInvoke (ptr);
This commit is contained in:
Родитель
ef03fa8bca
Коммит
779f064d04
|
@ -73,13 +73,9 @@ namespace CoreMidi {
|
|||
MidiThruConnectionRef ret;
|
||||
|
||||
using (var data = connectionParams.WriteStruct ()) {
|
||||
var retStr = CFString.CreateNative (persistentOwnerID);
|
||||
try {
|
||||
unsafe {
|
||||
error = MIDIThruConnectionCreate (retStr, data.Handle, &ret);
|
||||
}
|
||||
} finally {
|
||||
CFString.ReleaseNative (retStr);
|
||||
using var retStr = new TransientCFString (persistentOwnerID);
|
||||
unsafe {
|
||||
error = MIDIThruConnectionCreate (retStr, data.Handle, &ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,13 +151,9 @@ namespace CoreMidi {
|
|||
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (persistentOwnerID));
|
||||
|
||||
IntPtr ret;
|
||||
var persistentOwnerIDHandle = CFString.CreateNative (persistentOwnerID);
|
||||
try {
|
||||
unsafe {
|
||||
error = MIDIThruConnectionFind (persistentOwnerIDHandle, &ret);
|
||||
}
|
||||
} finally {
|
||||
CFString.ReleaseNative (persistentOwnerIDHandle);
|
||||
using var persistentOwnerIDHandle = new TransientCFString (persistentOwnerID);
|
||||
unsafe {
|
||||
error = MIDIThruConnectionFind (persistentOwnerIDHandle, &ret);
|
||||
}
|
||||
using (var data = Runtime.GetNSObject<NSData> (ret)) {
|
||||
if (data is null)
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using CoreFoundation;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace ObjCRuntime {
|
||||
// a short-lived holder for a CFString/NSString-like string for native interop
|
||||
// typical usage:
|
||||
// using var cstring = new NativeCFString (str);
|
||||
// SomePInvoke (cstring);
|
||||
//
|
||||
internal ref struct TransientCFString {
|
||||
#if !COREBUILD
|
||||
IntPtr ptr;
|
||||
|
||||
public TransientCFString (string? str)
|
||||
{
|
||||
ptr = CFString.CreateNative (str);
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
if (ptr != IntPtr.Zero) {
|
||||
CFString.ReleaseNative (ptr);
|
||||
ptr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator IntPtr (TransientCFString str) => str.ptr;
|
||||
public static explicit operator string? (TransientCFString str) => CFString.FromHandle (str.ptr);
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -82,22 +82,18 @@ namespace UIKit {
|
|||
[EditorBrowsable (EditorBrowsableState.Never)]
|
||||
public static void Main (string []? args, string? principalClassName, string? delegateClassName)
|
||||
{
|
||||
var p = CFString.CreateNative (principalClassName);
|
||||
var d = CFString.CreateNative (delegateClassName);
|
||||
using var p = new TransientCFString (principalClassName);
|
||||
using var d = new TransientCFString (delegateClassName);
|
||||
Initialize ();
|
||||
UIApplicationMain (args?.Length ?? 0, args, p, d);
|
||||
CFString.ReleaseNative (d);
|
||||
CFString.ReleaseNative (p);
|
||||
}
|
||||
|
||||
public static void Main (string []? args, Type? principalClass, Type? delegateClass)
|
||||
{
|
||||
var p = principalClass is null ? NativeHandle.Zero : CFString.CreateNative (new Class (principalClass).Name);
|
||||
var d = delegateClass is null ? NativeHandle.Zero : CFString.CreateNative (new Class (delegateClass).Name);
|
||||
using var p = new TransientCFString (principalClass is null ? null : new Class (principalClass).Name);
|
||||
using var d = new TransientCFString (delegateClass is null ? null : new Class (delegateClass).Name);
|
||||
Initialize ();
|
||||
UIApplicationMain (args?.Length ?? 0, args, p, d);
|
||||
CFString.ReleaseNative (d);
|
||||
CFString.ReleaseNative (p);
|
||||
}
|
||||
|
||||
public static void Main (string []? args)
|
||||
|
|
|
@ -1932,6 +1932,7 @@ SHARED_CORE_SOURCES = \
|
|||
ObjCRuntime/NativeAttribute.cs \
|
||||
ObjCRuntime/NativeHandle.cs \
|
||||
ObjCRuntime/NativeNameAttribute.cs \
|
||||
ObjCRuntime/TransientCFString.cs \
|
||||
ObjCRuntime/TransientString.cs \
|
||||
ObjCRuntime/NFloat.cs \
|
||||
ObjCRuntime/ObsoleteConstants.cs \
|
||||
|
|
|
@ -120,9 +120,16 @@ namespace Xamarin.Utils {
|
|||
if (provider?.HasCustomAttributes != true)
|
||||
return false;
|
||||
|
||||
foreach (var attrib in provider.CustomAttributes)
|
||||
if (IsObsoleteAttribute (attrib))
|
||||
return true;
|
||||
foreach (var attrib in provider.CustomAttributes) {
|
||||
if (!IsObsoleteAttribute (attrib))
|
||||
continue;
|
||||
|
||||
// The compiler will emit a fake Obsolete attribute for ref structs. Ignore those Obsolete attributes, because the type isn't really obsolete.
|
||||
if (attrib.HasConstructorArguments && attrib.ConstructorArguments [0].Value is string obsoleteMessage && obsoleteMessage == "Types with embedded references are not supported in this version of your compiler.")
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче