【问题标题】:Is [ComImport] considered P/Invoke?[ComImport] 是否被视为 P/Invoke?
【发布时间】:2012-01-18 14:18:28
【问题描述】:

什么是平台调用(P/Invoke)?


执行 P/Invoke 是什么意思?是calling an external dll吗?例如:

[DllImport("coredll.dll", SetLastError=true)]
private static extern bool SHGetSpecialFolderPath(
      int hwndOwner, 
      string lpszPath,
      ceFolders nFolder,
      bool fCreate);

这就是 P/Invoke 的意思:使用[DllImport] 属性吗?

还有什么可以被认为是P/Invoke

[ComImport] 呢?例如:

[System.Runtime.InteropServices.ComImport]
[Guid("F8383852-FCD3-11d1-A6B9-006097DF5BD4")]
public class ProgressDialog
{
}

注意:这个 COM 类 (F8383852-FCD3-11d1-A6B9-006097DF5BD4) 可以在

HKEY_CLASSES_ROOT\CLSID\{F8383852-FCD3-11d1-A6B9-006097DF5BD4}
      (default)       %SystemRoot%\system32\shell32.dll
      ThreadingModel  Both

我也可以用代码构造一个原生的ADO Recordset 对象:

[System.Runtime.InteropServices.ComImport]
[Guid("00000535-0000-0010-8000-00AA006D2EA4")]
public class Recordset
{
}

Object rs= new Recordset();

这算是 P/Invoke 吗?

如果我们选择说“P/Invoke 很糟糕”,那么 ComImport 是否与 DllImport 一样“糟糕”?

什么是平台调用(P/Invoke)?


更新:来自 MSDN:

Platform Invoke Tutorial

平台调用服务 (PInvoke) 允许托管代码调用 在 DLL 中实现的非托管函数。

C#代码可以直接调用非托管代码有两种方式:

我想我可能已经回答了我自己的问题。


一年半之后。现在没有人关注这个问题,也没有人喜欢它,我可以说我接受的答案是错误的。 P/InvokePlatform Invoke 的缩写。这是一种在 CLR 内部运行的托管代码可以调用非托管本机(即平台)代码的机制。这几乎总是通过调用驻留在本机 dll 中的代码来完成。 COM dll 本机代码;它们只是遵循严格的结构,以允许许多不同的编译器调用它们。

而且平台调用很糟糕。它绕过所有垃圾收集,并取决于平台(即我的 32 位 CLR 进程无法加载 64 位 dll,我为 Android 编写的应用程序无法在 Windows 上运行,我为 Windows 8 上的功能编写的应用程序将无法运行Windows XP)。

【问题讨论】:

  • "P/Invoke is bad" 这个陈述是错误的。它可能很糟糕,取决于几个因素,就像任何事情都可能很糟糕一样。任何做出这种笼统陈述的人只会表明他们缺乏经验。它还表明缺乏对 .NET Framework 工作原理的理解。
  • @Ramhound 感谢您不理解我在说什么。
  • 请注意您输入刚刚粘贴到更新中的部分的方式!请注意它提到了两种从 C# 调用非托管代码的方法,但并没有说它们都是 P/Invoke。事实上,COM 在那篇文章中没有其他地方提到过。其他文本强烈建议 P/Invoke 仅适用于这两点中的第一点。事实上,请注意 MSDN 上有一个单独的 COM Interop Tutorials 页面(参见导航栏),它与 Platform Invoke 不同。
  • P/invoke 本身当然不错。使用而不是完美的托管替代品,那么是的。用作访问本来无法访问的库的一种方式,没有托管替代方案,它非常好。例如,我的产品是一个非托管程序,它通过非托管 DLL 公开 API。您将如何建议 .net 消费者来访问它。没有托管替代方案。
  • @DavidHeffernan 这就是您创建独立于平台的托管替代方案的时候。如何在非英特尔设备上运行您的应用?

标签: c# com pinvoke


【解决方案1】:

不,它们不一样。 P/Invoke(平台调用)始终涉及使用 CLR 功能直接调用本机 DLL。 “本机 DLL”是指公开 extern "C" 函数的任何 DLL。托管 DLL 不允许您公开它们;这样的 DLL 通常是用 C/C++ 编写的。托管代码中 P/Invoke 的赠品签名是 DllImport 属性(或 C# 中的 extern 函数)。阅读 P/Invoke 页面并没有在任何地方提到 COM。

使用ComImport 是为了创建自定义互操作程序集(即手工制作的东西,而不是TlbImp 自动生成的PIA),并使用完全独立于P/Invoke 功能的固有CLR 功能,并且特定于 COM。

相似之处在于这两种方法都用于与非托管代码进行互操作。 CLR 都支持这两种方法,虽然理论上可以使用 Windows API 在托管代码中完全手动执行 COM 互操作,但是当 .NET 为您提供一种结构手段时,就主要或自定义互操作而言,这是没有意义的System.ComponentModel 中的程序集以及较低级别的支持。

【讨论】:

  • 感谢您的回答:-)
  • 我没有将ComImport 与自定义互操作程序集一起使用。我正在shell32.dll 中构建本机 com 类。是在原生 dll 的 not P/Invoke 中调用原生代码吗?
  • @rekire:没问题。无论如何,这很容易混淆,因为肯定有相似之处。
  • @IanBoyd:构建原生 com 类?你是什​​么意思? ComImport 仅与已定义的 COM 类型相关。
  • 不,无论如何,您不是执行 P/Invoke 的人。 .NET Framework 可能在相关的 Win32 DLL 上在内部执行了一个(我忘记了它是哪一个),但您自己肯定不是“p/invoking”。
猜你喜欢
  • 1970-01-01
  • 2012-11-24
  • 2022-06-25
  • 2012-02-24
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多