【问题标题】:How to pass InteropServices.ComTypes.IStream to native method accepting IStream* using c++/cli如何使用 c++/cli 将 InteropServices.ComTypes.IStream 传递给接受 IStream* 的本机方法
【发布时间】:2019-01-03 18:33:35
【问题描述】:

我有一个带有托管包装器的本机 dll,全部编写并使用 COM 互操作。我现在的工作是使用 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

【问题讨论】:

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


【解决方案1】:

我按照 Hans Passant 所说的方法解决了这个问题:

在 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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-17
    • 2016-04-21
    • 1970-01-01
    • 2015-01-24
    • 1970-01-01
    • 2011-08-31
    • 1970-01-01
    • 2013-11-14
    相关资源
    最近更新 更多