我有一个带有托管包装器的本机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
答案 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
}