gpt4 book ai didi

c# - DllImport 与 ComImport

转载 作者:搜寻专家 更新时间:2023-10-31 01:30:55 24 4
gpt4 key购买 nike

我试图围绕平台调用服务、组件对象模型等概念进行思考,但我发现很难理解什么是什么以及不同职责所在的位置。我一直在研究包含以下内容的代码:

[DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
[return: MarshalAs(UnmanagedType.Interface)]
internal static extern object SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IBindCtx pbc, ref Guid riid);

[ComImport]
[Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IShellItem

据我了解,前者导入一个创建 shell 项的函数,后者导入创建它们所需的类型(接口(interface))。

我不明白的是为什么一个使用 DllImport 而另一个使用 ComImport。它们各自的文档中没有说明使用哪种方法,文档中也没有提供 COM 对象的 GUID。我唯一的猜测是,区分因素是前者是一个函数而后者是一个接口(interface)。

最佳答案

IShellItem 是一个 COM 接口(interface)。一般而言,COM 与调用外部代码的 [DllImport] 方式相比效果不佳。 COM 更高级,一个接口(interface)声明了一整套您可以调用的方法,就像您在 C# 语言中使用 interface 关键字所做的那样。

在实践中,无论是在 C# 还是在 COM 中,您总是需要一个实现接口(interface)的具体类。在 COM 术语中称为 coclass,此类类完全隐藏在 View 之外。通常用 C++ 编写,这种语言通常对互操作的支持很差,但 COM 提供了使该 C++ 代码可从几乎任何语言调用的协议(protocol)。隐藏类实现是关键因素,完全隐藏讨厌的 C++ 小细节。像构造函数、内存管理、继承、对象布局、异常,以及从一种语言移植到另一种语言时非常糟糕的特性。

您总是需要使用工厂函数来创建类对象。一种通用的方法就是您正在谈论的方法, CoCreateInstance() 辅助函数非常常用。您需要提供的只是 CLSID,coclass 的 guid。然后 COM 运行时负责查找实现 coclass 的 EXE 或 DLL,加载它并获取 IClassFactory 接口(interface)以创建对象。必须注册 COM 服务器是至关重要的,注册表中的键告诉它哪个可执行文件负责该工作。

还有第二种方法,即由库显式导出的工厂函数,如 SHCreateItemFromParsingName()。它避免了我在上一段中提到的所有问题。 DirectX 不常见,但也不罕见,它是另一个使用工厂函数(如 D3D11CreateDevice())的库的好例子。微软何时更喜欢工厂函数而不是 coclass 并不是很明显,除了可能不鼓励从脚本语言使用这样的库。

如果该接口(interface)由一个组件类实现,那么您可以简单地使用 new IShellItem() 来创建该对象。请注意创建接口(interface)实例的奇怪之处,这在 C# 中是毫无意义的。但有意用于 COM 客户端代码。 C# 编译器在幕后生成代码以启动对象工厂管道。

但由于 SHCreateItemFromParsingName 工厂函数是从 DLL 导出的普通函数,就像其他任何函数一样,您现在需要使用 [DllImport] 来声明它。

关于c# - DllImport 与 ComImport,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46754843/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com