【发布时间】: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
【问题讨论】:
-
你有一个小的复制代码吗?魔鬼可以隐藏在细节中。
-
@kunif 我应该提到的,但似乎我忘记了。当我说 IStream 时,我的意思是 InteropServices.ComTypes.IStream 或 c++ 等价物。 (不是 std::istream)你发给我的文章似乎告诉我使用 ComTypes.IStream (我已经是),或者告诉我如何在托管代码中读取非托管流(而我需要做相反的事情。我不确定我是否遗漏了什么?
-
这些文章可能会有所帮助。 Chapter 8. IStreamとOleLoadPicture, simplestream.h, simplestream.cpp 虽然是日文,但通过谷歌翻译可以读懂。这是 C# 而不是 C++ 中的包装器示例。 Does a wrapper class for a COM interop IStream already exist? 结合起来你也许可以做点什么。
-
@SimonMourier 我已经更新了代码