1

I need to get a pointer e.g. of type byte* to an array of generic type. I found something but see pointer to a array of type generic?, nothing that solves my problem. My generic class doesn't have the where T: unmanaged restriction, but internally it works differently with managed and unmanaged types.

If (isUnamanged)
  //..
else
  //..

In the unamanged branch of the code, I'm using unsafe and thus need to get a pointer a to the generic array T[] and ensure it is pinned. I found a workable way using GCHandle.Alloc(genericArray, GCHandleType.Pinned), but it is very slow. The Unsafe class looks better...

fixed (byte* ptr = Unsafe.As<byte[]>(genericArray)) // genericArray is byte[], everything's fine (or no?)
{
  DoWork( ptr, arrByteSize);
}

fixed (long* ptr = Unsafe.As<long[]>(genericArray)) // genericArray is double[], ??? types differ, but type size is correct 
{
  DoWork( (byte*)ptr, arrByteSize);
}

fixed (byte* ptr = Unsafe.As<byte[]>(genericArray)) // genericArray is double[], ??? types differ and type size too 
{
  DoWork( ptr, arrByteSize);
}

This is what my question is related to (unless there is a better option for NET Framework 4.7.2). What I know in cast time is that the type is unmanaged and its byte size. Is it necessary to cast to exactly the right type to work properly, or is it possible to cast to a type that has the same byte count, or does it not matter what I cast to? The only thing I need from the "fixed" line is correctly fixed the entire array and return me a pointer to the beginning of the array, I've already taken care of the logic to keep the unsafe code out of the range of the array.

Alternatively if anyone knows a link to the source code that matches the fixed keyword.

Update after comments if Span is not the solution.

I need pointers to quickly copy a piece of data from one place to another, move data between multiple sources, etc. But from a specific size, say 1-2 MB, it is better to call some method from a library written in C/C++, for which I still need to get IntPtr somehow and fix the array. Moreover, I find the Span options quite limited (in 4.7.2). Is it possible to write T to indexes as well as arrays, but is it possible to e.g. write 100x T to any pointer, or write data types other than T, or change several bytes inside T?

Nullator
  • 71
  • 2
  • 1
    If you are using .NET Core 2.1 or later, you can use [MemoryMarshal.Cast](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.memorymarshal.cast) to cast from a `Span` to a `Span`. But you mention .NET Framework 4.7.2 so can you confirm you need to work in that version? – dbc Aug 28 '22 at 17:40
  • Why do you need `unsafe` in the first place, why do you need a raw pointer? What are you doing that `Soan` cannot do? – Charlieface Aug 28 '22 at 19:06
  • .NET won't let you (easily) use managed references in unmanaged context, because the GC can relocate objects at any time. You can Pin arrays, but general objects are AFAIK unpinnable :/ – exyi Sep 14 '22 at 21:34

0 Answers0