C# 使用CLI阵列分配的内存作为非托管类的存储
我有一个非托管类,它接受指向内存的指针作为其存储空间 e、 g 现在我试图包装这个类,以便从C#开始使用。显然,我希望能够将类似于C# 使用CLI阵列分配的内存作为非托管类的存储,c#,.net,c++-cli,mixed-mode,pin-ptr,C#,.net,C++ Cli,Mixed Mode,Pin Ptr,我有一个非托管类,它接受指向内存的指针作为其存储空间 e、 g 现在我试图包装这个类,以便从C#开始使用。显然,我希望能够将类似于float[]的东西传递给类。显然要做的事情是使用包装器类中的cli::pin_ptr public ref class MemBlockWrapper { MemBlock* mpMemBlock; public: MemBlockWrapper( array< float >^ fltArray ) { cli:
float[]
的东西传递给类。显然要做的事情是使用包装器类中的cli::pin_ptr
public ref class MemBlockWrapper
{
MemBlock* mpMemBlock;
public:
MemBlockWrapper( array< float >^ fltArray )
{
cli::pin_ptr< float > pFltArray = &fltArray[0];
// Brilliant we can now pass this pinned array to the C++ code.
mpMemBlock = new MemBlock( (void*)pFltArray );
// Now the pin_ptr goes out of scope ...
}
}
public ref类MemBlockWrapper
{
MemBlock*mpMemBlock;
公众:
MemBlockWrapper(数组^fltArray)
{
cli::pin_ptrpFltArray=&fltArray[0];
//辉煌我们现在可以把这个固定的数组传递给C++代码。
mpMemBlock=新的MemBlock((void*)pFltArray);
//现在pin_ptr超出范围。。。
}
}
但是,锁定ptr仅在cli::pin_ptr在范围内时有效。构造函数退出的时候,我不能再保证C++类的内存块是真的。
有没有办法在类的生命周期内固定指针?我做了很多搜索,只发现了一种使用“GCHandle”的方法,它看起来纯粹是用于托管C++(即不是C++ +CLI)。有人能告诉我一种确定地钉住和解开指针的方法吗
警告:这直接回答了问题,但在您尝试此方法之前,请先阅读并确保您确实了解发生了什么,并且仍然希望这样做
一个固定的GCHandle
将完成这项工作,它可以从C++/CLI中使用。很明显,只要确保手柄是固定式的
下面是一个例子:
public ref class MemBlockWrapper
{
MemBlock* mpMemBlock;
System::Runtime::InteropServices::GCHandle hFltArray;
public:
MemBlockWrapper(array< float >^ fltArray)
{
hFltArray = System::Runtime::InteropServices::GCHandle::Alloc(
fltArray,
System::Runtime::InteropServices::GCHandleType::Pinned);
mpMemBlock = new MemBlock(hFltArray.AddrOfPinnedObject().ToPointer());
}
~MemBlockWrapper()
{
this->!MemBlockWrapper();
}
!MemBlockWrapper()
{
if (mpMemBlock)
{
delete mpMemBlock;
mpMemBlock = nullptr;
hFltArray.Free();
}
}
};
public ref类MemBlockWrapper
{
MemBlock*mpMemBlock;
System::Runtime::InteropServices::GCHandle hFltArray;
公众:
MemBlockWrapper(数组^fltArray)
{
hFltArray=System::Runtime::InteropServices::GCHandle::Alloc(
弗塔雷,
系统::运行时::互操作服务::GCHandleType::固定);
mpMemBlock=newmemblock(hFltArray.AddrOfPinnedObject().ToPointer());
}
~MemBlockWrapper()
{
此->!MemBlockWrapper();
}
!MemBlockWrapper()
{
if(mpMemBlock)
{
删除mpMemBlock;
mpMemBlock=nullptr;
hFltArray.Free();
}
}
};
我添加了一个析构函数和一个终结器,这样,即使忘记处理包装器,也可以获得一次性
模式和安全清理
警告:这直接回答了问题,但在您尝试此方法之前,请先阅读并确保您确实了解发生了什么,并且仍然希望这样做
一个固定的GCHandle
将完成这项工作,它可以从C++/CLI中使用。很明显,只要确保手柄是固定式的
下面是一个例子:
public ref class MemBlockWrapper
{
MemBlock* mpMemBlock;
System::Runtime::InteropServices::GCHandle hFltArray;
public:
MemBlockWrapper(array< float >^ fltArray)
{
hFltArray = System::Runtime::InteropServices::GCHandle::Alloc(
fltArray,
System::Runtime::InteropServices::GCHandleType::Pinned);
mpMemBlock = new MemBlock(hFltArray.AddrOfPinnedObject().ToPointer());
}
~MemBlockWrapper()
{
this->!MemBlockWrapper();
}
!MemBlockWrapper()
{
if (mpMemBlock)
{
delete mpMemBlock;
mpMemBlock = nullptr;
hFltArray.Free();
}
}
};
public ref类MemBlockWrapper
{
MemBlock*mpMemBlock;
System::Runtime::InteropServices::GCHandle hFltArray;
公众:
MemBlockWrapper(数组^fltArray)
{
hFltArray=System::Runtime::InteropServices::GCHandle::Alloc(
弗塔雷,
系统::运行时::互操作服务::GCHandleType::固定);
mpMemBlock=newmemblock(hFltArray.AddrOfPinnedObject().ToPointer());
}
~MemBlockWrapper()
{
此->!MemBlockWrapper();
}
!MemBlockWrapper()
{
if(mpMemBlock)
{
删除mpMemBlock;
mpMemBlock=nullptr;
hFltArray.Free();
}
}
};
我添加了一个析构函数和一个终结器,这样,即使忘记处理包装,您也可以获得
一次性
模式和安全清理。当然,您不能使用pin\u ptr。GCHandle在VB.NET中的可用性与在C#中的可用性一样,在C++/CLI中的可用性与在“托管C++”中的可用性一样。顺便说一句,后两种语言没有区别,只是语法不同。GCHandle是一种普通的.NET类型,可用于任何与.NET兼容的语言
不,你正在考虑的是一个非常糟糕的主意。长时间固定阵列是非常有害的。“long”取决于垃圾回收器的运行速度,一般来说,超过几秒钟的钉住是非常糟糕的,几分钟的钉住是不可能的
固定对象是道路上的一块石头,垃圾收集器在压缩堆时必须不断绕过它,这会降低堆的使用效率。当它是堆段中唯一剩余的对象时,就会出现真正的问题,它无法回收,而且该数组现在需要花费您两兆字节。在服务器上添加多只手和脚
一旦你得到了少数,你接下来只考虑简单地复制数组。从
数组^
到使用新的[]运算符分配的浮点[]
。没什么大不了的,以每秒7把千兆字节的速度运行,不给不给。当然,你不能使用pin_ptr。GCHandle在VB.NET中的可用性与在C#中的可用性一样,在C++/CLI中的可用性与在“托管C++”中的可用性一样。顺便说一句,后两种语言没有区别,只是语法不同。GCHandle是一种普通的.NET类型,可用于任何与.NET兼容的语言
不,你正在考虑的是一个非常糟糕的主意。长时间固定阵列是非常有害的。“long”取决于垃圾回收器的运行速度,一般来说,超过几秒钟的钉住是非常糟糕的,几分钟的钉住是不可能的
固定对象是道路上的一块石头,垃圾收集器在压缩堆时必须不断绕过它,这会降低堆的使用效率。当它是堆段中唯一剩余的对象时,就会出现真正的问题,它无法回收,而且该数组现在需要花费您两兆字节。在服务器上添加多只手和脚
一旦你得到了少数,你接下来只考虑简单地复制数组。从
array^
到float[]
t