Reputation: 225
I'm trying to adapt a vendor's c# example code for interfacing with a PCI-Express device. The code basically allocates a large buffer as an int array, and then pins it via the fixed keyword before handing it off to hardware to be filled with data.
This works great, but it eventually fails because .Net is limited to ~2 billion elements in an array. I can push the limit out to 16 GB by using an array of Long and gcAllowVeryLargeObjects keyword, but eventually I still run into .Net limitations.
In unmanaged code I could call VirtualAlloc and request 40 or 50GB directly, however its not clear to me if this is possible in c# and I haven't been able to find any good example code. I realize I could be doing this in a different language, but on Windows at least I'm more familiar with .Net, and aside from this relatively small portion of the program, there is very little hardware-specific code so I'd like to try and stick with what I have.
Upvotes: 2
Views: 8147
Reputation: 63722
gcAllowVeryLargeObjects should work just fine, are you sure it doesn't? You may have to explicitly set the target CPU to x64 only.
In any case, you could use a hack struct
to get a large value-type (which you can use as an array):
unsafe struct Test
{
public fixed byte Data[1024];
}
unsafe void Main()
{
Test[] test = new Test[16 * 1024 * 1024];
// We've got 16 * 1024 * 1024 * 1024 here.
fixed (Test* pTest = test)
{
}
}
This does have its limits (the unsafe structure has a maximum size), but it should get you where you need to be.
However, it might be better idea to simply call VirtualAlloc
through P/Invoke. Or better, use Marshal.AllocHGlobal
, it should really be doing the same thing (although you can't specify any parameters except for the size).
Upvotes: 1
Reputation: 6337
You can pinvoke VirtualAlloc. The signature is
[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType lAllocationType, MemoryProtection flProtect);
You can find most pinvoke structures and signatures on pinvoke.net: VirtualAlloc
Alternatively, take a look at the AllocHGlobal func
Upvotes: 8