6

我正在尝试编写一个将使用 DirectShow 的小型库。该库将由 .NET 应用程序使用,因此我认为最好用 C++/CLI 编写它。

但是,我在这条线上遇到了麻烦:

    HRESULT hr = CoCreateInstance(  CLSID_FilterGraph,
                                    NULL,
                                    CLSCTX_INPROC_SERVER,
                                    IID_IGraphBuilder,
                                    (void**)(&graphBuilder) );  //error C2440:

在哪里graphBuilder声明:

public ref class VideoPlayer
{
public:
    VideoPlayer();
    void Load(String^ filename);

    IGraphBuilder*  graphBuilder;

};

如果我正确理解了这个页面,我可以*/&像往常一样在我的 C++/CLI 库中使用指向非托管内存的“本机”指针;^用于表示指向托管对象的指针。但是,此代码产生:

错误 C2440:“类型转换”:无法从“cli::interior_ptr”转换为“void **”

该错误表明它graphBuilder被认为是一个'cli::interior_ptr<Type>'. 那是托管内存的指针/句柄,不是吗?但它是一个纯本机指针。我不想将指针传递给期望句柄的方法,反之亦然 - 我只是想将它存储在我的托管类中)如果是这样,我怎么说graphBuilder是“传统”指针?

这个问题很相似,但答案是,要使用 pin_ptr,我看不到对我有帮助,因为它不能成为我班级的成员)

4

1 回答 1

11

错误消息有点神秘,但编译器试图提醒您不能将指向托管类成员的指针传递给非托管代码。这在设计上是行不通的,当垃圾收集器在函数执行时启动并移动托管对象时,灾难就会发生。在进程中使指向成员的指针无效并导致本机代码将字节喷射到错误地址的 gc 堆中。

解决方法很简单,只需声明一个局部变量并将指针传递给它。堆栈上的变量不能移动。像这样:

void init() {
    IGraphBuilder* builder;    // Local variable, okay to pass its address
    HRESULT hr = CoCreateInstance(CLSID_FilterGraph,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_IGraphBuilder,
        (void**)(&builder) );
    if (SUCCEEDED(hr)) {
        graphBuilder = builder;
        // etc...
    }
}
于 2012-05-06T18:03:00.777 回答