如何使用c ++ / cli

时间:2019-01-03 18:33:35

标签: c++ com c++-cli

我有一个带有托管包装器的本机dll,全部都编写并与COM interop一起使用。现在,我的工作是使用c ++ / cli重写包装程序(和dll的一部分)。

本机dll中的一种方法接受指针 IStream *输出作为其参数之一,这就是我遇到的问题。每当我尝试使用指针 output 时,都会收到 AccessViolationException

以下是我的代码的示例:

common.h

class INativeClass
{
public:
    virtual int NativeMethod(IStream* output) = 0;
};

c ++原生

#include "common.h"

public NativeClass : public INativeClass  
{  
    public int NativeMethod(IStream* output)  
    {  
        outputStream->Write(...); //AccessViolationException happens here
    }  
}

由c ++管理

#include "common.h"

public ref class ManagedClass  
{  
private:  
    INativeClass* nativeObject;  

public: 

    ManagedClass()  
    {  
        nativeObject = CreateNewNativeObject();  
    }  

    int ManagedMethod(IStream^ output)  
    {  
        NativeClass nativeObject = new 
        GCHandle streamHandle = GCHandle::Alloc(output);  
        IntPtr ipo = GCHandle::ToIntPtr(streamHandle);  
        nativeObject->NativeMethod(static_cast<IStream*>(ipo.ToPointer()));  
    }  
}  

c#

void main()  
{  
    ManagedClass managedObject = new ManagedClass();  
    IStreamImplementation stream = new IStreamImplementation(filepath);  
    managedObject.ManagedMethod(stream);  
}

我已经在互联网上搜索了几天,但似乎找不到我做错了什么。我认为我已正确转换为 IStream * ,并且我不必担心GC。我也尝试使用 pin_ptr ,但这没有帮助。

如果这是重复的话,我表示歉意,但是正如我所说,我已经在寻找解决方案已有几天了。

编辑

使用可以解决该问题的最少可编译代码更新了代码(可能缺少其中的一些内容)。
同样,当我说IStream时,我的意思是InteropServices.ComTypes.IStream或它的c ++对应对象。我没有使用std :: istream

1 个答案:

答案 0 :(得分:1)

我已经按照汉斯·帕桑特的说法解决了这个问题:

在ManagedClass中,我有:

int ManagedMethod (IStream^ output)
{
    IntPtr outputPtr = Marshal::GetIUnknownForObject(output);
    IUnknown* outputNativePtr = static_cast<IUnknown*>(outputPtr.ToPointer());
    nativeObject->NativeMethod(outputNativePtr);
}

在NativeClass中,我有:

int NativeMethod(IUnknown* output)
{
    IStream outputStream;
    HRESULT hr = output->QueryInterface(IID_IStream, (void**)&outputStream);
    if (FAILED(hr) || outputStream == nullptr)
    {
        //error
    }
    //do something
}