You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by we...@apache.org on 2023/07/06 17:07:23 UTC
[arrow] branch main updated: GH-35809: [C#] Improvements to the C Data Interface (#35810)
This is an automated email from the ASF dual-hosted git repository.
westonpace pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 88cb517012 GH-35809: [C#] Improvements to the C Data Interface (#35810)
88cb517012 is described below
commit 88cb5170121489da3f39ee75912c680e92941fd9
Author: Theodore Tsirpanis <te...@tsirpanis.gr>
AuthorDate: Thu Jul 6 20:07:15 2023 +0300
GH-35809: [C#] Improvements to the C Data Interface (#35810)
### Rationale for this change
This PR fixes issues identified while reading the code of the `Apache.Arrow.C` namespace.
### What changes are included in this PR?
See each commit message for more details.
### Are these changes tested?
Using the existing test suite.
### Are there any user-facing changes?
No.
* Closes: #35809
Authored-by: Theodore Tsirpanis <te...@tsirpanis.gr>
Signed-off-by: Weston Pace <we...@gmail.com>
---
csharp/src/Apache.Arrow/Apache.Arrow.csproj | 4 ++
csharp/src/Apache.Arrow/C/CArrowArray.cs | 17 +++----
csharp/src/Apache.Arrow/C/CArrowArrayExporter.cs | 28 ++++++++----
csharp/src/Apache.Arrow/C/CArrowArrayImporter.cs | 2 +-
csharp/src/Apache.Arrow/C/CArrowArrayStream.cs | 30 ++++++++----
.../Apache.Arrow/C/CArrowArrayStreamExporter.cs | 53 +++++++++++++++++++---
.../Apache.Arrow/C/CArrowArrayStreamImporter.cs | 23 ++++++++--
csharp/src/Apache.Arrow/C/CArrowSchema.cs | 16 +++----
csharp/src/Apache.Arrow/C/CArrowSchemaExporter.cs | 11 ++++-
csharp/src/Apache.Arrow/C/NativeDelegate.cs | 7 ++-
.../Apache.Arrow.Tests/CDataInterfaceDataTests.cs | 2 +-
.../CDataInterfaceSchemaTests.cs | 2 +-
12 files changed, 136 insertions(+), 59 deletions(-)
diff --git a/csharp/src/Apache.Arrow/Apache.Arrow.csproj b/csharp/src/Apache.Arrow/Apache.Arrow.csproj
index c57c8e48b9..43d60ba001 100644
--- a/csharp/src/Apache.Arrow/Apache.Arrow.csproj
+++ b/csharp/src/Apache.Arrow/Apache.Arrow.csproj
@@ -44,4 +44,8 @@
<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible($(TargetFramework), 'net5.0'))">
<Compile Remove="Arrays\HalfFloatArray.cs" />
</ItemGroup>
+ <ItemGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible($(TargetFramework), 'net5.0'))">
+ <!-- Code targeting .NET 5+ should use [UnmanagedCallersOnly]. -->
+ <Compile Remove="C\NativeDelegate.cs" />
+ </ItemGroup>
</Project>
diff --git a/csharp/src/Apache.Arrow/C/CArrowArray.cs b/csharp/src/Apache.Arrow/C/CArrowArray.cs
index 4aba95add0..a8a084d1d7 100644
--- a/csharp/src/Apache.Arrow/C/CArrowArray.cs
+++ b/csharp/src/Apache.Arrow/C/CArrowArray.cs
@@ -38,7 +38,11 @@ namespace Apache.Arrow.C
public byte** buffers;
public CArrowArray** children;
public CArrowArray* dictionary;
- public delegate* unmanaged[Stdcall]<CArrowArray*, void> release;
+ internal delegate* unmanaged
+#if !NET5_0_OR_GREATER
+ [Cdecl]
+#endif
+ <CArrowArray*, void> release;
public void* private_data;
/// <summary>
@@ -51,16 +55,7 @@ namespace Apache.Arrow.C
{
var ptr = (CArrowArray*)Marshal.AllocHGlobal(sizeof(CArrowArray));
- ptr->length = 0;
- ptr->n_buffers = 0;
- ptr->offset = 0;
- ptr->buffers = null;
- ptr->n_children = 0;
- ptr->children = null;
- ptr->dictionary = null;
- ptr->null_count = 0;
- ptr->release = null;
- ptr->private_data = null;
+ *ptr = default;
return ptr;
}
diff --git a/csharp/src/Apache.Arrow/C/CArrowArrayExporter.cs b/csharp/src/Apache.Arrow/C/CArrowArrayExporter.cs
index aafb3b8987..5a793c177e 100644
--- a/csharp/src/Apache.Arrow/C/CArrowArrayExporter.cs
+++ b/csharp/src/Apache.Arrow/C/CArrowArrayExporter.cs
@@ -15,6 +15,7 @@
using System;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Apache.Arrow.Memory;
@@ -22,9 +23,13 @@ namespace Apache.Arrow.C
{
public static class CArrowArrayExporter
{
+#if NET5_0_OR_GREATER
+ private static unsafe delegate* unmanaged<CArrowArray*, void> ReleaseArrayPtr => &ReleaseArray;
+#else
private unsafe delegate void ReleaseArrowArray(CArrowArray* cArray);
private static unsafe readonly NativeDelegate<ReleaseArrowArray> s_releaseArray = new NativeDelegate<ReleaseArrowArray>(ReleaseArray);
-
+ private static unsafe delegate* unmanaged[Cdecl]<CArrowArray*, void> ReleaseArrayPtr => (delegate* unmanaged[Cdecl]<CArrowArray*, void>)s_releaseArray.Pointer;
+#endif
/// <summary>
/// Export an <see cref="IArrowArray"/> to a <see cref="CArrowArray"/>. Whether or not the
/// export succeeds, the original array becomes invalid. Clone an array to continue using it
@@ -54,7 +59,7 @@ namespace Apache.Arrow.C
try
{
ConvertArray(allocationOwner, array.Data, cArray);
- cArray->release = (delegate* unmanaged[Stdcall]<CArrowArray*, void>)(IntPtr)s_releaseArray.Pointer;
+ cArray->release = ReleaseArrayPtr;
cArray->private_data = FromDisposable(allocationOwner);
allocationOwner = null;
}
@@ -97,7 +102,7 @@ namespace Apache.Arrow.C
try
{
ConvertRecordBatch(allocationOwner, batch, cArray);
- cArray->release = (delegate* unmanaged[Stdcall]<CArrowArray*, void>)s_releaseArray.Pointer;
+ cArray->release = ReleaseArrayPtr;
cArray->private_data = FromDisposable(allocationOwner);
allocationOwner = null;
}
@@ -112,7 +117,7 @@ namespace Apache.Arrow.C
cArray->length = array.Length;
cArray->offset = array.Offset;
cArray->null_count = array.NullCount;
- cArray->release = (delegate* unmanaged[Stdcall]<CArrowArray*, void>)s_releaseArray.Pointer;
+ cArray->release = ReleaseArrayPtr;
cArray->private_data = null;
cArray->n_buffers = array.Buffers?.Length ?? 0;
@@ -157,7 +162,7 @@ namespace Apache.Arrow.C
cArray->length = batch.Length;
cArray->offset = 0;
cArray->null_count = 0;
- cArray->release = (delegate* unmanaged[Stdcall]<CArrowArray*, void>)s_releaseArray.Pointer;
+ cArray->release = ReleaseArrayPtr;
cArray->private_data = null;
cArray->n_buffers = 1;
@@ -180,13 +185,12 @@ namespace Apache.Arrow.C
cArray->dictionary = null;
}
+#if NET5_0_OR_GREATER
+ [UnmanagedCallersOnly]
+#endif
private unsafe static void ReleaseArray(CArrowArray* cArray)
{
- if (cArray->private_data != null)
- {
- Dispose(&cArray->private_data);
- }
- cArray->private_data = null;
+ Dispose(&cArray->private_data);
cArray->release = null;
}
@@ -199,6 +203,10 @@ namespace Apache.Arrow.C
private unsafe static void Dispose(void** ptr)
{
GCHandle gch = GCHandle.FromIntPtr((IntPtr)(*ptr));
+ if (!gch.IsAllocated)
+ {
+ return;
+ }
((IDisposable)gch.Target).Dispose();
gch.Free();
*ptr = null;
diff --git a/csharp/src/Apache.Arrow/C/CArrowArrayImporter.cs b/csharp/src/Apache.Arrow/C/CArrowArrayImporter.cs
index 4375b382d9..e1314e5a62 100644
--- a/csharp/src/Apache.Arrow/C/CArrowArrayImporter.cs
+++ b/csharp/src/Apache.Arrow/C/CArrowArrayImporter.cs
@@ -164,7 +164,7 @@ namespace Apache.Arrow.C
case ArrowTypeId.Map:
break;
case ArrowTypeId.Null:
- buffers = new ArrowBuffer[0];
+ buffers = System.Array.Empty<ArrowBuffer>();
break;
case ArrowTypeId.Dictionary:
DictionaryType dictionaryType = (DictionaryType)type;
diff --git a/csharp/src/Apache.Arrow/C/CArrowArrayStream.cs b/csharp/src/Apache.Arrow/C/CArrowArrayStream.cs
index bf1fcb39ef..a900a6895a 100644
--- a/csharp/src/Apache.Arrow/C/CArrowArrayStream.cs
+++ b/csharp/src/Apache.Arrow/C/CArrowArrayStream.cs
@@ -35,7 +35,11 @@ namespace Apache.Arrow.C
///
/// Return value: 0 if successful, an `errno`-compatible error code otherwise.
///</summary>
- public delegate* unmanaged[Stdcall]<CArrowArrayStream*, CArrowSchema*, int> get_schema;
+ internal delegate* unmanaged
+#if !NET5_0_OR_GREATER
+ [Cdecl]
+#endif
+ <CArrowArrayStream*, CArrowSchema*, int> get_schema;
/// <summary>
/// Callback to get the next array. If no error and the array is released, the stream has ended.
@@ -43,7 +47,11 @@ namespace Apache.Arrow.C
///
/// Return value: 0 if successful, an `errno`-compatible error code otherwise.
/// </summary>
- public delegate* unmanaged[Stdcall]<CArrowArrayStream*, CArrowArray*, int> get_next;
+ internal delegate* unmanaged
+#if !NET5_0_OR_GREATER
+ [Cdecl]
+#endif
+ <CArrowArrayStream*, CArrowArray*, int> get_next;
/// <summary>
/// Callback to get optional detailed error information. This must only
@@ -54,13 +62,21 @@ namespace Apache.Arrow.C
/// Return value: pointer to a null-terminated character array describing the last
/// error, or NULL if no description is available.
///</summary>
- public delegate* unmanaged[Stdcall]<CArrowArrayStream*, byte*> get_last_error;
+ internal delegate* unmanaged
+#if !NET5_0_OR_GREATER
+ [Cdecl]
+#endif
+ <CArrowArrayStream*, byte*> get_last_error;
/// <summary>
/// Release callback: release the stream's own resources. Note that arrays returned by
/// get_next must be individually released.
/// </summary>
- public delegate* unmanaged[Stdcall]<CArrowArrayStream*, void> release;
+ internal delegate* unmanaged
+#if !NET5_0_OR_GREATER
+ [Cdecl]
+#endif
+ <CArrowArrayStream*, void> release;
public void* private_data;
@@ -74,11 +90,7 @@ namespace Apache.Arrow.C
{
var ptr = (CArrowArrayStream*)Marshal.AllocHGlobal(sizeof(CArrowArrayStream));
- ptr->get_schema = null;
- ptr->get_next = null;
- ptr->get_last_error = null;
- ptr->release = null;
- ptr->private_data = null;
+ *ptr = default;
return ptr;
}
diff --git a/csharp/src/Apache.Arrow/C/CArrowArrayStreamExporter.cs b/csharp/src/Apache.Arrow/C/CArrowArrayStreamExporter.cs
index 911dd7a153..56e0468f94 100644
--- a/csharp/src/Apache.Arrow/C/CArrowArrayStreamExporter.cs
+++ b/csharp/src/Apache.Arrow/C/CArrowArrayStreamExporter.cs
@@ -15,6 +15,7 @@
using System;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Apache.Arrow.Ipc;
@@ -22,14 +23,29 @@ namespace Apache.Arrow.C
{
public static class CArrowArrayStreamExporter
{
+#if NET5_0_OR_GREATER
+ private static unsafe delegate* unmanaged<CArrowArrayStream*, CArrowSchema*, int> GetSchemaPtr => &GetSchema;
+ private static unsafe delegate* unmanaged<CArrowArrayStream*, CArrowArray*, int> GetNextPtr => &GetNext;
+ private static unsafe delegate* unmanaged<CArrowArrayStream*, byte*> GetLastErrorPtr => &GetLastError;
+ private static unsafe delegate* unmanaged<CArrowArrayStream*, void> ReleasePtr => &Release;
+#else
private unsafe delegate int GetSchemaArrayStream(CArrowArrayStream* cArrayStream, CArrowSchema* cSchema);
private static unsafe NativeDelegate<GetSchemaArrayStream> s_getSchemaArrayStream = new NativeDelegate<GetSchemaArrayStream>(GetSchema);
+ private static unsafe delegate* unmanaged[Cdecl]<CArrowArrayStream*, CArrowSchema*, int> GetSchemaPtr =>
+ (delegate* unmanaged[Cdecl]<CArrowArrayStream*, CArrowSchema*, int>)s_getSchemaArrayStream.Pointer;
private unsafe delegate int GetNextArrayStream(CArrowArrayStream* cArrayStream, CArrowArray* cArray);
private static unsafe NativeDelegate<GetNextArrayStream> s_getNextArrayStream = new NativeDelegate<GetNextArrayStream>(GetNext);
+ private static unsafe delegate* unmanaged[Cdecl]<CArrowArrayStream*, CArrowArray*, int> GetNextPtr =>
+ (delegate* unmanaged[Cdecl]<CArrowArrayStream*, CArrowArray*, int>)s_getNextArrayStream.Pointer;
private unsafe delegate byte* GetLastErrorArrayStream(CArrowArrayStream* cArrayStream);
private static unsafe NativeDelegate<GetLastErrorArrayStream> s_getLastErrorArrayStream = new NativeDelegate<GetLastErrorArrayStream>(GetLastError);
+ private static unsafe delegate* unmanaged[Cdecl]<CArrowArrayStream*, byte*> GetLastErrorPtr =>
+ (delegate* unmanaged[Cdecl]<CArrowArrayStream*, byte*>)s_getLastErrorArrayStream.Pointer;
private unsafe delegate void ReleaseArrayStream(CArrowArrayStream* cArrayStream);
private static unsafe NativeDelegate<ReleaseArrayStream> s_releaseArrayStream = new NativeDelegate<ReleaseArrayStream>(Release);
+ private static unsafe delegate* unmanaged[Cdecl]<CArrowArrayStream*, void> ReleasePtr =>
+ (delegate* unmanaged[Cdecl]<CArrowArrayStream*, void>)s_releaseArrayStream.Pointer;
+#endif
/// <summary>
/// Export an <see cref="IArrowArrayStream"/> to a <see cref="CArrowArrayStream"/>.
@@ -55,12 +71,15 @@ namespace Apache.Arrow.C
}
cArrayStream->private_data = ExportedArrayStream.Export(arrayStream);
- cArrayStream->get_schema = (delegate* unmanaged[Stdcall]<CArrowArrayStream*, CArrowSchema*, int>)s_getSchemaArrayStream.Pointer;
- cArrayStream->get_next = (delegate* unmanaged[Stdcall]<CArrowArrayStream*, CArrowArray*, int>)s_getNextArrayStream.Pointer;
- cArrayStream->get_last_error = (delegate* unmanaged[Stdcall]<CArrowArrayStream*, byte*>)s_getLastErrorArrayStream.Pointer;
- cArrayStream->release = (delegate* unmanaged[Stdcall]<CArrowArrayStream*, void>)s_releaseArrayStream.Pointer;
+ cArrayStream->get_schema = GetSchemaPtr;
+ cArrayStream->get_next = GetNextPtr;
+ cArrayStream->get_last_error = GetLastErrorPtr;
+ cArrayStream->release = ReleasePtr;
}
+#if NET5_0_OR_GREATER
+ [UnmanagedCallersOnly]
+#endif
private unsafe static int GetSchema(CArrowArrayStream* cArrayStream, CArrowSchema* cSchema)
{
ExportedArrayStream arrayStream = null;
@@ -76,6 +95,9 @@ namespace Apache.Arrow.C
}
}
+#if NET5_0_OR_GREATER
+ [UnmanagedCallersOnly]
+#endif
private unsafe static int GetNext(CArrowArrayStream* cArrayStream, CArrowArray* cArray)
{
ExportedArrayStream arrayStream = null;
@@ -96,6 +118,9 @@ namespace Apache.Arrow.C
}
}
+#if NET5_0_OR_GREATER
+ [UnmanagedCallersOnly]
+#endif
private unsafe static byte* GetLastError(CArrowArrayStream* cArrayStream)
{
try
@@ -109,10 +134,12 @@ namespace Apache.Arrow.C
}
}
+#if NET5_0_OR_GREATER
+ [UnmanagedCallersOnly]
+#endif
private unsafe static void Release(CArrowArrayStream* cArrayStream)
{
- ExportedArrayStream arrayStream = ExportedArrayStream.FromPointer(cArrayStream->private_data);
- arrayStream.Dispose();
+ ExportedArrayStream.Free(&cArrayStream->private_data);
cArrayStream->release = null;
}
@@ -136,6 +163,18 @@ namespace Apache.Arrow.C
return (void*)GCHandle.ToIntPtr(gch);
}
+ public static void Free(void** ptr)
+ {
+ GCHandle gch = GCHandle.FromIntPtr((IntPtr)ptr);
+ if (!gch.IsAllocated)
+ {
+ return;
+ }
+ ((ExportedArrayStream)gch.Target).Dispose();
+ gch.Free();
+ *ptr = null;
+ }
+
public static ExportedArrayStream FromPointer(void* ptr)
{
GCHandle gch = GCHandle.FromIntPtr((IntPtr)ptr);
@@ -166,7 +205,7 @@ namespace Apache.Arrow.C
{
if (LastError != null)
{
- Marshal.FreeCoTaskMem((IntPtr)LastError);
+ Marshal.FreeHGlobal((IntPtr)LastError);
LastError = null;
}
}
diff --git a/csharp/src/Apache.Arrow/C/CArrowArrayStreamImporter.cs b/csharp/src/Apache.Arrow/C/CArrowArrayStreamImporter.cs
index b2558f07a4..7e70632bf8 100644
--- a/csharp/src/Apache.Arrow/C/CArrowArrayStreamImporter.cs
+++ b/csharp/src/Apache.Arrow/C/CArrowArrayStreamImporter.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation (ASF) under one
+// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
@@ -55,6 +55,16 @@ namespace Apache.Arrow.C
private readonly Schema _schema;
private bool _disposed;
+ internal static string GetLastError(CArrowArrayStream* arrayStream, int errno)
+ {
+ byte* error = arrayStream->get_last_error(arrayStream);
+ if (error == null)
+ {
+ return $"Array stream operation failed with no message. Error code: {errno}";
+ }
+ return StringUtil.PtrToStringUtf8(error);
+ }
+
public ImportedArrowArrayStream(CArrowArrayStream* cArrayStream)
{
if (cArrayStream == null)
@@ -70,7 +80,7 @@ namespace Apache.Arrow.C
int errno = cArrayStream->get_schema(cArrayStream, &cSchema);
if (errno != 0)
{
- throw new Exception($"Unexpected error recieved from external stream. Errno: {errno}");
+ throw new Exception(GetLastError(cArrayStream, errno));
}
_schema = CArrowSchemaImporter.ImportSchema(&cSchema);
@@ -92,6 +102,11 @@ namespace Apache.Arrow.C
throw new ObjectDisposedException(typeof(ImportedArrowArrayStream).Name);
}
+ if (cancellationToken.IsCancellationRequested)
+ {
+ return new(Task.FromCanceled<RecordBatch>(cancellationToken));
+ }
+
RecordBatch result = null;
CArrowArray cArray = new CArrowArray();
fixed (CArrowArrayStream* cArrayStream = &_cArrayStream)
@@ -99,7 +114,7 @@ namespace Apache.Arrow.C
int errno = cArrayStream->get_next(cArrayStream, &cArray);
if (errno != 0)
{
- throw new Exception($"Unexpected error recieved from external stream. Errno: {errno}");
+ return new(Task.FromException<RecordBatch>(new Exception(GetLastError(cArrayStream, errno))));
}
if (cArray.release != null)
{
@@ -115,7 +130,7 @@ namespace Apache.Arrow.C
if (!_disposed && _cArrayStream.release != null)
{
_disposed = true;
- fixed (CArrowArrayStream * cArrayStream = &_cArrayStream)
+ fixed (CArrowArrayStream* cArrayStream = &_cArrayStream)
{
cArrayStream->release(cArrayStream);
}
diff --git a/csharp/src/Apache.Arrow/C/CArrowSchema.cs b/csharp/src/Apache.Arrow/C/CArrowSchema.cs
index af01247800..64761dbd0d 100644
--- a/csharp/src/Apache.Arrow/C/CArrowSchema.cs
+++ b/csharp/src/Apache.Arrow/C/CArrowSchema.cs
@@ -39,7 +39,11 @@ namespace Apache.Arrow.C
public long n_children;
public CArrowSchema** children;
public CArrowSchema* dictionary;
- public delegate* unmanaged[Stdcall]<CArrowSchema*, void> release;
+ internal delegate* unmanaged
+#if !NET5_0_OR_GREATER
+ [Cdecl]
+#endif
+ <CArrowSchema*, void> release;
public void* private_data;
/// <summary>
@@ -52,15 +56,7 @@ namespace Apache.Arrow.C
{
var ptr = (CArrowSchema*)Marshal.AllocHGlobal(sizeof(CArrowSchema));
- ptr->format = null;
- ptr->name = null;
- ptr->metadata = null;
- ptr->flags = 0;
- ptr->n_children = 0;
- ptr->children = null;
- ptr->dictionary = null;
- ptr->release = null;
- ptr->private_data = null;
+ *ptr = default;
return ptr;
}
diff --git a/csharp/src/Apache.Arrow/C/CArrowSchemaExporter.cs b/csharp/src/Apache.Arrow/C/CArrowSchemaExporter.cs
index fe47c9f7f0..9053e80664 100644
--- a/csharp/src/Apache.Arrow/C/CArrowSchemaExporter.cs
+++ b/csharp/src/Apache.Arrow/C/CArrowSchemaExporter.cs
@@ -18,6 +18,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using Apache.Arrow.Types;
@@ -26,8 +27,13 @@ namespace Apache.Arrow.C
{
public static class CArrowSchemaExporter
{
+#if NET5_0_OR_GREATER
+ private static unsafe delegate* unmanaged<CArrowSchema*, void> ReleaseSchemaPtr => &ReleaseCArrowSchema;
+#else
private unsafe delegate void ReleaseArrowSchema(CArrowSchema* cArray);
private static unsafe readonly NativeDelegate<ReleaseArrowSchema> s_releaseSchema = new NativeDelegate<ReleaseArrowSchema>(ReleaseCArrowSchema);
+ private static unsafe delegate* unmanaged[Cdecl]<CArrowSchema*, void> ReleaseSchemaPtr => (delegate* unmanaged[Cdecl]<CArrowSchema*, void>)s_releaseSchema.Pointer;
+#endif
/// <summary>
/// Export a type to a <see cref="CArrowSchema"/>.
@@ -63,7 +69,7 @@ namespace Apache.Arrow.C
schema->dictionary = ConstructDictionary(datatype);
- schema->release = (delegate* unmanaged[Stdcall]<CArrowSchema*, void>)s_releaseSchema.Pointer;
+ schema->release = ReleaseSchemaPtr;
schema->private_data = null;
}
@@ -285,6 +291,9 @@ namespace Apache.Arrow.C
ptr += length;
}
+#if NET5_0_OR_GREATER
+ [UnmanagedCallersOnly]
+#endif
private static unsafe void ReleaseCArrowSchema(CArrowSchema* schema)
{
if (schema == null) return;
diff --git a/csharp/src/Apache.Arrow/C/NativeDelegate.cs b/csharp/src/Apache.Arrow/C/NativeDelegate.cs
index 48b37fbfe5..ebc6330c9b 100644
--- a/csharp/src/Apache.Arrow/C/NativeDelegate.cs
+++ b/csharp/src/Apache.Arrow/C/NativeDelegate.cs
@@ -20,17 +20,16 @@ using System.Runtime.InteropServices;
namespace Apache.Arrow.C
{
- internal readonly struct NativeDelegate<T>
+ internal readonly struct NativeDelegate<T> where T : Delegate
{
private readonly T _managedDelegate; // For lifetime management
- private readonly IntPtr _nativePointer;
public NativeDelegate(T managedDelegate)
{
_managedDelegate = managedDelegate;
- _nativePointer = Marshal.GetFunctionPointerForDelegate<T>(managedDelegate);
+ Pointer = Marshal.GetFunctionPointerForDelegate(managedDelegate);
}
- public IntPtr Pointer { get { return _nativePointer; } }
+ public IntPtr Pointer { get; }
}
}
diff --git a/csharp/test/Apache.Arrow.Tests/CDataInterfaceDataTests.cs b/csharp/test/Apache.Arrow.Tests/CDataInterfaceDataTests.cs
index 89a346f9f7..a430e140cf 100644
--- a/csharp/test/Apache.Arrow.Tests/CDataInterfaceDataTests.cs
+++ b/csharp/test/Apache.Arrow.Tests/CDataInterfaceDataTests.cs
@@ -77,7 +77,7 @@ namespace Apache.Arrow.Tests
wasCalled = true;
cArray->release = null;
};
- cArray->release = (delegate* unmanaged[Stdcall]<CArrowArray*, void>)Marshal.GetFunctionPointerForDelegate(
+ cArray->release = (delegate* unmanaged<CArrowArray*, void>)Marshal.GetFunctionPointerForDelegate(
releaseCallback);
Assert.Throws<InvalidOperationException>(() =>
diff --git a/csharp/test/Apache.Arrow.Tests/CDataInterfaceSchemaTests.cs b/csharp/test/Apache.Arrow.Tests/CDataInterfaceSchemaTests.cs
index a75d777ad3..dfd6f9912c 100644
--- a/csharp/test/Apache.Arrow.Tests/CDataInterfaceSchemaTests.cs
+++ b/csharp/test/Apache.Arrow.Tests/CDataInterfaceSchemaTests.cs
@@ -105,7 +105,7 @@ namespace Apache.Arrow.Tests
wasCalled = true;
cSchema->release = null;
};
- cSchema->release = (delegate* unmanaged[Stdcall]<CArrowSchema*, void>)Marshal.GetFunctionPointerForDelegate(
+ cSchema->release = (delegate* unmanaged<CArrowSchema*, void>)Marshal.GetFunctionPointerForDelegate(
releaseCallback);
Assert.Throws<NullReferenceException>(() =>