【发布时间】:2022-01-16 15:36:22
【问题描述】:
[不是重复的,我已经搜索了几天的解决方案并进行了很多测试,但没有发现任何真正有用的东西。这就是我注册 stackoverflow 并发布此内容的原因。]
[情况]
我正在尝试在 C# 中执行 COM 互操作,但我不太熟悉 COM 的工作原理。
有一个没有任何 .tlb 文件的 COM 库。幸运的是,我在 github 上的一个开放存储库中找到了它的 .idl 文件。然后我将接口声明复制到我自己的项目中,并用 C# 重写了它们。
一切看起来都很棒只有在我只是检索可以从中调用方法的 COM 对象。这就是这个库的工作原理。
[问题]
问题是,这个库请求实现一个接口来执行 IO 操作,调用者应该自定义(例如重定向到标准输出/文件/打印机)。
它迫使我通过调用dllimport 库中的stdcall 函数来提供此接口的实例。
我尽我所能,总是失败。
具体看下面的代码。
[代码]
// The interface I rewrote from .idl file which I must give implementation of.
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(<GUID>)]
public interface IFoo
{
int Bar(string s);
}
// The implementation I would like to provide
[ClassInterface(ClassInterfaceType.None), Guid<GUID>]
public class MyFoo : IFoo
{
public int Bar(string s)
{
Console.Write(s);
return 0; //S_OK
}
}
// This is the delegate for the function.
// The function itself is obtained by GetProcAddress
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int Function(IntPtr obj);
// Here's the code I used
Function func = <GetProcAddress stuff>;
IFoo obj = new MyFoo();
IntPtr objPtr = Marshal.GetIUnknownForObject(obj);
int hresult = Function(objPtr);
if (hresult != 0) // S_OK
throw new Exception($"Failed 0x{hresult:x}");
[到目前为止]
如果此函数成功,hresult 应该为 0(S_OK),但它只是不断得到0x80131515。
好吧,我确信问题与Function无关,因为我发现另一个sn-p的代码成功了。
该代码无需重新声明接口然后实现,而是通过用函数指针填充接口手动构造接口的 VTable。
这真的不是我想要的,因为代码看起来不那么干净,也不那么安全。
几天来我一直在寻找解决方案,但几乎没有找到关于此的信息。看来 COM 已经过时了。
【问题讨论】:
-
你想要做什么远不清楚。您将 COM 与 GetProcAddress 混合的代码毫无意义。你有一个完全复制的项目吗? PS:COM远未过时。
-
@SimonMourier 对不起,实际上我是从 mscordacwks.dll 调用
CLRDataCreateInstance。那是一个导出的 C-Style 函数,所以我只能这样称呼它。我发现 clrMD 也是这样做的。但是它构建了自己的VTable来提供实现,看这个:link我只是尝试重新声明interface ICLRDataTarget然后显式实现它。 -
@SimonMourier 此外,getprocaddress stuff 显示了它的调用。 my repo 这是我的仓库,README 显示了问题所在。
-
我没有看到任何与 COM 严格相关的问题。该错误似乎是合法的。但是系统也在查询 ICLRDataTarget2、ICLRDataTarget3、ICLRMetadataLocator(以及另一个未知的),我认为您也必须实现 ICLRMetadataLocator。
-
@SimonMourier 没错,但我首先尝试从 clrMD 的代码中删除现有的
ICLRMetadataLocator和ICLRRuntimeLocator实现,令人惊讶的是它仍然运行良好。只有在将其翻译为显式之后,它才会发生故障。我对CLRDataCreateInstance进行了一些原生调试,发现问题就像你说的那样,它正在查询其他几个接口但失败了。嗯,问题解决了,谢谢。
标签: c# com interop marshalling unmanaged