我有一个非托管函数,它接受malloc分配的一块内存,稍后以异步方式释放它。我想将它包装到托管包装器中。下面的代码好吗?
void managed_fx (byte data __gc[], size_t size)
{
// Pin the data
byte __pin *pinned_data = &data [0];
// Copy data to the unmanaged buffer.
void *unmanaged_data = malloc (size);
memcpy (unmanaged_data, (byte*) pinned_data, size);
// Forward the call
fx (unmanaged_data, size);
}
发布于 2019-04-18 08:30:58
好吧,让我们更简单:
void managed_fx (byte data __gc[])
{
// Pin the data
byte __pin *pinned_data = &data [0];
// Copy data to the unmanaged buffer.
void *unmanaged_data = malloc (data.Length);
assert (unmanaged_data);
memcpy (unmanaged_data, (byte*) pinned_data, data.Length);
// Forward the call
fx (unamanged_data, data.Length);
}
不过,我还有几个问题:
发布于 2019-04-18 09:28:59
你是
考虑到这一点,这是一个固定的版本
void managed_fx (byte data __gc[], size_t size)
{
if (data.Length < size)
throw gcnew System.IndexOutOfRangeException(
"the unmanaged buffer is not big enough");
// Pin the data
byte __pin *pinned_data = &data [0];
// Copy data to the unmanaged buffer.
void *unmanaged_data = malloc (size);
if (unmanaged_data == NULL)
throw gcnew OutOfMemoryException(
"could not allocate memory for the unmanaged buffer");
memcpy (unmanaged_data, (byte*) pinned_data, size);
// Forward the call
fx (unamanged_data, size);
}
要回答进一步的问题:
执行memcpy需要固定。它不会阻止GC运行时删除内存(技术上确实如此,但只是保持对它的引用)它会阻止它在内存中移动。由于memcpy是一个非托管函数 - 它无法处理它正在操作的指针在内存中移动。malloc完全不受管理(尽管运行时库可以自由地使用托管堆的保留区域来执行此操作)。
源代码C ++ / CLI中没有明确区分“代码”是管理还是非管理。关于编译一些部分将是CIL中间代码,其他普通本机代码重要的是是否是变量使用的是托管或非托管。托管引用(带有^的任何内容)只能由本身管理的代码操作/使用。这意味着如果运行时改变了内存中托管对象的位置,那么运行时可以自由地改变它认为合适的底层指针的值。它以对托管函数安全的方式执行此操作(它们在围绕它们改变世界时暂停)。由于存在许多有用的函数,并且不知道如何处理这样的托管引用,因此最终可能需要使用一个简单的指针。由于此操作不安全(如果GC启动移动引用),存在固定指针以使这安全且简单,因为它都需要一个指针并且该指针的生命期阻止运行时将指向变量移动。
https://stackoverflow.com/questions/-100001127
复制相似问题