[ObjCRuntime/bgen] Add support for (s)byte, (u)short and nuint fields. (#21141)

This commit is contained in:
Rolf Bjarne Kvinge 2024-08-29 20:14:52 +02:00 коммит произвёл GitHub
Родитель bd35d0d2e5
Коммит 56de4fa92e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
8 изменённых файлов: 267 добавлений и 0 удалений

Просмотреть файл

@ -203,6 +203,114 @@ namespace ObjCRuntime {
return Runtime.GetNSObject<NSNumber> (actual);
}
/// <summary>Gets the signed byte value exposed with the given symbol from the dynamic library.</summary>
/// <param name="handle">Handle to the dynamic library previously opened with <see cref="dlopen(System.String,System.Int32)" /> or <see cref="dlopen(System.String,Mode)" />.</param>
/// <param name="symbol">Name of the public symbol in the dynamic library to look up.</param>
/// <returns>The value from the library, or zero on failure.</returns>
/// <remarks>If this routine fails, it will return zero.</remarks>
public static sbyte GetSByte (IntPtr handle, string symbol)
{
var indirect = dlsym (handle, symbol);
if (indirect == IntPtr.Zero)
return 0;
unchecked {
return (sbyte) Marshal.ReadByte (indirect);
}
}
/// <summary>Sets the specified symbol in the library handle to the specified signed byte value.</summary>
/// <param name="handle">Handle to the dynamic library previously opened with <see cref="dlopen(System.String,System.Int32)" /> or <see cref="dlopen(System.String,Mode)" />.</param>
/// <param name="symbol">Name of the public symbol in the dynamic library to look up.</param>
/// <param name="value">The value to set.</param>
public static void SetSByte (IntPtr handle, string symbol, sbyte value)
{
var indirect = dlsym (handle, symbol);
if (indirect == IntPtr.Zero)
return;
unsafe {
Marshal.WriteByte (indirect, (byte) value);
}
}
/// <summary>Gets the byte value exposed with the given symbol from the dynamic library.</summary>
/// <param name="handle">Handle to the dynamic library previously opened with <see cref="dlopen(System.String,System.Int32)" /> or <see cref="dlopen(System.String,Mode)" />.</param>
/// <param name="symbol">Name of the public symbol in the dynamic library to look up.</param>
/// <returns>The value from the library, or zero on failure.</returns>
/// <remarks>If this routine fails, it will return zero.</remarks>
public static byte GetByte (IntPtr handle, string symbol)
{
var indirect = dlsym (handle, symbol);
if (indirect == IntPtr.Zero)
return 0;
return Marshal.ReadByte (indirect);
}
/// <summary>Sets the specified symbol in the library handle to the specified byte value.</summary>
/// <param name="handle">Handle to the dynamic library previously opened with <see cref="dlopen(System.String,System.Int32)" /> or <see cref="dlopen(System.String,Mode)" />.</param>
/// <param name="symbol">Name of the public symbol in the dynamic library to look up.</param>
/// <param name="value">The value to set.</param>
public static void SetByte (IntPtr handle, string symbol, byte value)
{
var indirect = dlsym (handle, symbol);
if (indirect == IntPtr.Zero)
return;
Marshal.WriteByte (indirect, value);
}
/// <summary>Gets the short value exposed with the given symbol from the dynamic library.</summary>
/// <param name="handle">Handle to the dynamic library previously opened with <see cref="dlopen(System.String,System.Int32)" /> or <see cref="dlopen(System.String,Mode)" />.</param>
/// <param name="symbol">Name of the public symbol in the dynamic library to look up.</param>
/// <returns>The value from the library, or zero on failure.</returns>
/// <remarks>If this routine fails, it will return zero.</remarks>
public static short GetInt16 (IntPtr handle, string symbol)
{
var indirect = dlsym (handle, symbol);
if (indirect == IntPtr.Zero)
return 0;
return Marshal.ReadInt16 (indirect);
}
/// <summary>Sets the specified symbol in the library handle to the specified short value.</summary>
/// <param name="handle">Handle to the dynamic library previously opened with <see cref="dlopen(System.String,System.Int32)" /> or <see cref="dlopen(System.String,Mode)" />.</param>
/// <param name="symbol">Name of the public symbol in the dynamic library to look up.</param>
/// <param name="value">The value to set.</param>
public static void SetInt16 (IntPtr handle, string symbol, short value)
{
var indirect = dlsym (handle, symbol);
if (indirect == IntPtr.Zero)
return;
Marshal.WriteInt16 (indirect, value);
}
/// <summary>Gets the ushort value exposed with the given symbol from the dynamic library.</summary>
/// <param name="handle">Handle to the dynamic library previously opened with <see cref="dlopen(System.String,System.Int32)" /> or <see cref="dlopen(System.String,Mode)" />.</param>
/// <param name="symbol">Name of the public symbol in the dynamic library to look up.</param>
/// <returns>The value from the library, or zero on failure.</returns>
/// <remarks>If this routine fails, it will return zero.</remarks>
public static ushort GetUInt16 (IntPtr handle, string symbol)
{
var indirect = dlsym (handle, symbol);
if (indirect == IntPtr.Zero)
return 0;
unchecked {
return (ushort) Marshal.ReadInt16 (indirect);
}
}
/// <summary>Sets the specified symbol in the library handle to the specified ushort value.</summary>
/// <param name="handle">Handle to the dynamic library previously opened with <see cref="dlopen(System.String,System.Int32)" /> or <see cref="dlopen(System.String,Mode)" />.</param>
/// <param name="symbol">Name of the public symbol in the dynamic library to look up.</param>
/// <param name="value">The value to set.</param>
public static void SetUInt16 (IntPtr handle, string symbol, ushort value)
{
var indirect = dlsym (handle, symbol);
if (indirect == IntPtr.Zero)
return;
unchecked {
Marshal.WriteInt16 (indirect, (short) value);
}
}
public static int GetInt32 (IntPtr handle, string symbol)
{
var indirect = dlsym (handle, symbol);

Просмотреть файл

@ -6339,6 +6339,14 @@ public partial class Generator : IMemberGatherer {
print ("_{0} = Runtime.GetNSObject<UTType> (Dlfcn.GetIntPtr (Libraries.{2}.Handle, \"{1}\"))!;", field_pi.Name, fieldAttr.SymbolName, library_name);
indent--;
print ("return _{0};", field_pi.Name);
} else if (field_pi.PropertyType == TypeCache.System_Byte) {
print ("return Dlfcn.GetByte (Libraries.{2}.Handle, \"{1}\");", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_SByte) {
print ("return Dlfcn.GetSByte (Libraries.{2}.Handle, \"{1}\");", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_Int16) {
print ("return Dlfcn.GetInt16 (Libraries.{2}.Handle, \"{1}\");", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_UInt16) {
print ("return Dlfcn.GetUInt16 (Libraries.{2}.Handle, \"{1}\");", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_Int32) {
print ("return Dlfcn.GetInt32 (Libraries.{2}.Handle, \"{1}\");", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_UInt32) {
@ -6349,6 +6357,8 @@ public partial class Generator : IMemberGatherer {
print ("return Dlfcn.GetFloat (Libraries.{2}.Handle, \"{1}\");", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_IntPtr) {
print ("return Dlfcn.GetIntPtr (Libraries.{2}.Handle, \"{1}\");", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_UIntPtr) {
print ("return Dlfcn.GetUIntPtr (Libraries.{2}.Handle, \"{1}\");", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType.FullName == "System.Drawing.SizeF") {
print ("return Dlfcn.GetSizeF (Libraries.{2}.Handle, \"{1}\");", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_Int64) {
@ -6419,10 +6429,20 @@ public partial class Generator : IMemberGatherer {
print ("Dlfcn.SetUInt32 (Libraries.{2}.Handle, \"{1}\", value);", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_Double) {
print ("Dlfcn.SetDouble (Libraries.{2}.Handle, \"{1}\", value);", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_Byte) {
print ("Dlfcn.SetByte (Libraries.{2}.Handle, \"{1}\", value);", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_SByte) {
print ("Dlfcn.SetSByte (Libraries.{2}.Handle, \"{1}\", value);", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_Int16) {
print ("Dlfcn.SetInt16 (Libraries.{2}.Handle, \"{1}\", value);", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_UInt16) {
print ("Dlfcn.SetUInt16 (Libraries.{2}.Handle, \"{1}\", value);", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_Float) {
print ("Dlfcn.SetFloat (Libraries.{2}.Handle, \"{1}\", value);", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_IntPtr) {
print ("Dlfcn.SetIntPtr (Libraries.{2}.Handle, \"{1}\", value);", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_UIntPtr) {
print ("Dlfcn.SetUIntPtr (Libraries.{2}.Handle, \"{1}\", value);", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType.FullName == "System.Drawing.SizeF") {
print ("Dlfcn.SetSizeF (Libraries.{2}.Handle, \"{1}\", value);", field_pi.Name, fieldAttr.SymbolName, library_name);
} else if (field_pi.PropertyType == TypeCache.System_Int64) {

Просмотреть файл

@ -1675,6 +1675,22 @@ namespace GeneratorTests {
}
}
[Test]
[TestCase (Profile.iOS)]
public void UnderlyingFieldType (Profile profile)
{
Configuration.IgnoreIfIgnoredPlatform (profile.AsPlatform ());
var bgen = BuildFile (profile, true, true, "tests/underlyingfieldtype.cs");
#if NET
const string nintName = "System.IntPtr";
const string nuintName = "System.UIntPtr";
#else
const string nintName = "System.nint";
const string nuintName = "System.nuint";
#endif
}
[Test]
[TestCase (Profile.iOS)]
public void DelegatesWithNullableReturnType (Profile profile)

Просмотреть файл

@ -0,0 +1,40 @@
using System;
using Foundation;
namespace UnderlyingFieldType {
[BaseType (typeof (NSObject))]
interface FieldClass {
[Field ("SByteField", "__Internal")]
sbyte SByteField { get; set; }
[Field ("ByteField", "__Internal")]
byte ByteField { get; set; }
[Field ("ShortField", "__Internal")]
short ShortField { get; set; }
[Field ("UShortField", "__Internal")]
ushort UShortField { get; set; }
[Field ("IntField", "__Internal")]
int IntField { get; set; }
[Field ("UIntField", "__Internal")]
uint UIntField { get; set; }
[Field ("LongField", "__Internal")]
long LongField { get; set; }
[Field ("ULongField", "__Internal")]
ulong ULongField { get; set; }
[Field ("DoubleField", "__Internal")]
double DoubleField { get; set; }
[Field ("UIntPtrField", "__Internal")]
UIntPtr UIntPtrField { get; set; }
[Field ("IntPtrield", "__Internal")]
IntPtr IntPtrField { get; set; }
}
}

Просмотреть файл

@ -33,5 +33,83 @@ namespace MonoTouchFixtures.ObjCRuntime {
#endif
Assert.That (err, Is.EqualTo (expected), "dlclose");
}
#if NET
[Test]
public void GetVariables ()
{
var symbol = "x_native_field";
var handle = (IntPtr) Dlfcn.RTLD.Default;
Assert.AreNotEqual (IntPtr.Zero, Dlfcn.dlsym (handle, symbol), "Symbol");
var originalValue = Dlfcn.GetUInt64 (handle, symbol);
Assert.Multiple (() => {
unchecked {
// the n(uint) and (U)IntPtr asserts only work in 64-bit, which is fine because we only care about 64-bit right now.
Assert.AreEqual ((ushort) 0x8899, (ushort) Dlfcn.GetInt16 (handle, symbol), "GetInt16");
Assert.AreEqual ((uint) 0xeeff8899, (uint) Dlfcn.GetInt32 (handle, symbol), "GetInt32");
Assert.AreEqual ((ulong) 0xaabbccddeeff8899, (ulong) Dlfcn.GetInt64 (handle, symbol), "GetInt64");
Assert.AreEqual ((nuint) 0xaabbccddeeff8899, (nuint) Dlfcn.GetNInt (handle, symbol), "GetNInt");
Assert.AreEqual ((ushort) 0x8899, Dlfcn.GetUInt16 (handle, symbol), "GetUInt16");
Assert.AreEqual ((uint) 0xeeff8899, Dlfcn.GetUInt32 (handle, symbol), "GetUInt32");
Assert.AreEqual ((ulong) 0xaabbccddeeff8899, Dlfcn.GetUInt64 (handle, symbol), "GetUInt64");
Assert.AreEqual ((nuint) 0xaabbccddeeff8899, Dlfcn.GetNUInt (handle, symbol), "GetNUInt");
Assert.AreEqual ((nfloat) (-7.757653393002521E-103), Dlfcn.GetNFloat (handle, symbol), "GetNFloat");
Assert.AreEqual (-7.7576533930025207E-103d, Dlfcn.GetDouble (handle, symbol), "GetDouble");
Assert.AreEqual ((nuint) 0xaabbccddeeff8899, (nuint) Dlfcn.GetIntPtr (handle, symbol), "GetIntPtr"); // won't work in 32-bit, but we don't care about that anymore
Assert.AreEqual ((nuint) 0xaabbccddeeff8899, Dlfcn.GetUIntPtr (handle, symbol), "GetUIntPtr");
Dlfcn.SetInt16 (handle, symbol, 0x77);
Assert.AreEqual ((short) 0x77, Dlfcn.GetInt16 (handle, symbol), "SetInt16");
Dlfcn.SetUInt64 (handle, symbol, originalValue);
Dlfcn.SetInt32 (handle, symbol, 0x77);
Assert.AreEqual ((int) 0x77, Dlfcn.GetInt32 (handle, symbol), "SetInt32");
Dlfcn.SetUInt64 (handle, symbol, originalValue);
Dlfcn.SetInt64 (handle, symbol, 0x77);
Assert.AreEqual ((long) 0x77, Dlfcn.GetInt64 (handle, symbol), "SetInt64");
Dlfcn.SetUInt64 (handle, symbol, originalValue);
Dlfcn.SetNInt (handle, symbol, 0x77);
Assert.AreEqual ((nint) 0x77, Dlfcn.GetNInt (handle, symbol), "SetNInt");
Dlfcn.SetUInt64 (handle, symbol, originalValue);
Dlfcn.SetUInt16 (handle, symbol, 0x77);
Assert.AreEqual ((ushort) 0x77, Dlfcn.GetUInt16 (handle, symbol), "SetUInt16");
Dlfcn.SetUInt64 (handle, symbol, originalValue);
Dlfcn.SetUInt32 (handle, symbol, 0x77);
Assert.AreEqual ((uint) 0x77, Dlfcn.GetUInt32 (handle, symbol), "SetUInt32");
Dlfcn.SetUInt64 (handle, symbol, originalValue);
Dlfcn.SetUInt64 (handle, symbol, 0x77);
Assert.AreEqual ((ulong) 0x77, Dlfcn.GetUInt64 (handle, symbol), "SetUInt64");
Dlfcn.SetUInt64 (handle, symbol, originalValue);
Dlfcn.SetNUInt (handle, symbol, 0x77);
Assert.AreEqual ((nuint) 0x77, Dlfcn.GetNUInt (handle, symbol), "SetNUInt");
Dlfcn.SetUInt64 (handle, symbol, originalValue);
Dlfcn.SetNFloat (handle, symbol, 0x77);
Assert.AreEqual ((nfloat) 0x77, Dlfcn.GetNFloat (handle, symbol), "SetNFloat");
Dlfcn.SetUInt64 (handle, symbol, originalValue);
Dlfcn.SetDouble (handle, symbol, 0x77);
Assert.AreEqual (0x77, Dlfcn.GetDouble (handle, symbol), "SetDouble");
Dlfcn.SetUInt64 (handle, symbol, originalValue);
Dlfcn.SetIntPtr (handle, symbol, 0x77);
Assert.AreEqual ((nint) 0x77, Dlfcn.GetIntPtr (handle, symbol), "SetIntPtr");
Dlfcn.SetUInt64 (handle, symbol, originalValue);
Dlfcn.SetUIntPtr (handle, symbol, 0x77);
Assert.AreEqual ((nuint) 0x77, Dlfcn.GetUIntPtr (handle, symbol), "SetUIntPtr");
Dlfcn.SetUInt64 (handle, symbol, originalValue);
}
});
}
#endif
}
}

Просмотреть файл

@ -48,6 +48,7 @@
<ItemGroup>
<ReferenceNativeSymbol Include="Inexistent" SymbolType="ObjectiveCClass" SymbolMode="Ignore" />
<ReferenceNativeSymbol Include="x_native_field" SymbolType="Field" />
</ItemGroup>
<Import Project="$(RootTestsDirectory)/common/shared-dotnet.csproj" />

Просмотреть файл

@ -17,6 +17,8 @@ extern "C" {
int theUltimateAnswer ();
void useZLib ();
__attribute__ ((used)) unsigned long long x_native_field = 0xAABBCCDDEEFF8899;
// NS_ASSUME_NONNULL_BEGIN doesn't work
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnullability-completeness"

Просмотреть файл

@ -74,6 +74,7 @@
#define x_SCNMatrix4MakeScale object_x_SCNMatrix4MakeScale
#define x_SCNMatrix4Translate object_x_SCNMatrix4Translate
#define x_GlobalString object_x_GlobalString
#define x_native_field object_x_native_field
#elif PREFIX == 2
#define theUltimateAnswer ar_theUltimateAnswer
#define useZLib ar_useZLib
@ -149,6 +150,7 @@
#define x_SCNMatrix4MakeScale ar_x_SCNMatrix4MakeScale
#define x_SCNMatrix4Translate ar_x_SCNMatrix4Translate
#define x_GlobalString ar_x_GlobalString
#define x_native_field ar_x_native_field
#else
// keep original names
#endif