Skip to content

Instantly share code, notes, and snippets.

@ufcpp
Last active September 22, 2020 05:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ufcpp/eda2c50c65b3daa4ee8a0fa9bbbbc4d0 to your computer and use it in GitHub Desktop.
Save ufcpp/eda2c50c65b3daa4ee8a0fa9bbbbc4d0 to your computer and use it in GitHub Desktop.
多次元配列の AsSpan
using System;
using System.Runtime.InteropServices;
public class Program
{
static void Main()
{
var x = new uint[] { 0xDEADBEEF, 1, 2, 3, 4, 5, 6, 7 };
var y = new uint[,] { { 0xDEADBEEF, 1, 2, 3 }, { 4, 5, 6, 7 } };
var z = new uint[,,] { { { 0xDEADBEEF, 1 }, { 2, 3 } }, { { 4, 5 }, { 6, 7 } } };
Write(x.AsSpan());
Write(AsSpan(y));
Write(AsSpan(z));
}
// MemoryMarshal.CreateSpan が .NET Core 2.1 以降限定…
static Span<T> AsSpan<T>(T[,] a) => MemoryMarshal.CreateSpan(ref a[0, 0], a.Length);
static Span<T> AsSpan<T>(T[,,] a) => MemoryMarshal.CreateSpan(ref a[0, 0, 0], a.Length);
static Span<T> AsSpan<T>(Array a)
{
// 任意ランクの Array に対して先頭要素の ref を取る手段がなさそうなので switch…
switch (a)
{
case T[] x: return x.AsSpan();
case T[,] x: return AsSpan(x);
case T[,,] x: return AsSpan(x);
default: throw new InvalidOperationException();
}
}
static void Write<T>(Span<T> span)
{
foreach (var x in span)
{
Console.Write(x);
Console.Write(' ');
}
Console.WriteLine();
}
}
public unsafe void Send<T>(string name, Array array)
where T : unmanaged
{
long[] dims = new long[array.Rank];
for (int i = 0; i < dims.Length; i++)
{
dims[i] = array.GetLength(i);
}
//一次元の長さの配列を用意
var span = AsSpan<T>(array);
fixed (void* address = span)
{
IntPtr npArray = NumPy.PyArrayNewFromDescr(NumPy.PyArrayType, Dtype.Int32, array.Rank, dims, null, address, NpConsts.NPY_ARRAY_CARRAY, IntPtr.Zero);
PyObject.SetAttr(name, npArray);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment