Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用CLI阵列分配的内存作为非托管类的存储_C#_.net_C++ Cli_Mixed Mode_Pin Ptr - Fatal编程技术网

C# 使用CLI阵列分配的内存作为非托管类的存储

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:

我有一个非托管类,它接受指向内存的指针作为其存储空间

e、 g

现在我试图包装这个类,以便从C#开始使用。显然,我希望能够将类似于
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