编组指向数组的指针 P/Invoke
Marshalling pointer to array P/Invoke
我正在使用 P/Invoke
在 .NET
核心中包装一个共享对象库 (FFTW)
。 FFTW
需要分配可能在特定边界上对齐的内存,因此我需要使用它的内存分配例程。理想情况下,我想避免在托管数组中创建单独的内存块并在每次使用时复制数据。理想情况下,创建数组以指向已分配的内存。这可能吗,还是我应该放弃并接受副本的性能影响?
不,您不能创建指向已由外部内存管理器分配的非托管内存的 array。但是,您可以创建一个 Span<T>
或一个 Memory<T>
,这会给您一个 非常相似的 API,这意味着您不需要unsafe
之后的任何时候。请注意,为了能够将它存储在任何地方,它需要是一个 Memory<T>
(Span<T>
是一个 ref struct
)——但是 Memory<T>
本质上只是一个按需跨度提供商 - 当您需要跨度时,请在您的 Memory<T>
.
上调用 .Span
现在;没有 Memory<T>
用于处理开箱即用的原始指针,但编写一个很简单。或者您可以只使用 this one I wrote earlier(MemoryManager<T>
是一种抽象,可用于实现自定义 Memory<T>
实例,然后可以在需要时提供 Span<T>
)。
用法:
int* ptr = ...
int len = ...
var memory = new UnmanagedMemoryManager<int>(ptr, len).Memory;
// (I should probably add a helper method for that!)
这给你一个 Memory<int>
可以存储在字段等中;然后使用它,你想要跨度:
var span = _memory.Span;
span[42] = 119; // etc
你也可以在跨度上做强制类型转换之类的事情,允许它们做指针可以做的大部分相同的事情(即以同样的方式你可以强制一个 int*
成为一个 byte*
,你可以在相同的内存中将 Span<int>
转换成 Span<byte>
- 不是副本)。
我正在使用 P/Invoke
在 .NET
核心中包装一个共享对象库 (FFTW)
。 FFTW
需要分配可能在特定边界上对齐的内存,因此我需要使用它的内存分配例程。理想情况下,我想避免在托管数组中创建单独的内存块并在每次使用时复制数据。理想情况下,创建数组以指向已分配的内存。这可能吗,还是我应该放弃并接受副本的性能影响?
不,您不能创建指向已由外部内存管理器分配的非托管内存的 array。但是,您可以创建一个 Span<T>
或一个 Memory<T>
,这会给您一个 非常相似的 API,这意味着您不需要unsafe
之后的任何时候。请注意,为了能够将它存储在任何地方,它需要是一个 Memory<T>
(Span<T>
是一个 ref struct
)——但是 Memory<T>
本质上只是一个按需跨度提供商 - 当您需要跨度时,请在您的 Memory<T>
.
.Span
现在;没有 Memory<T>
用于处理开箱即用的原始指针,但编写一个很简单。或者您可以只使用 this one I wrote earlier(MemoryManager<T>
是一种抽象,可用于实现自定义 Memory<T>
实例,然后可以在需要时提供 Span<T>
)。
用法:
int* ptr = ...
int len = ...
var memory = new UnmanagedMemoryManager<int>(ptr, len).Memory;
// (I should probably add a helper method for that!)
这给你一个 Memory<int>
可以存储在字段等中;然后使用它,你想要跨度:
var span = _memory.Span;
span[42] = 119; // etc
你也可以在跨度上做强制类型转换之类的事情,允许它们做指针可以做的大部分相同的事情(即以同样的方式你可以强制一个 int*
成为一个 byte*
,你可以在相同的内存中将 Span<int>
转换成 Span<byte>
- 不是副本)。