简体   繁体   English

pInvoke 和 COM Interop 有什么区别?

[英]What is the difference between pInvoke and COM Interop?

Let us say that I am accessing a third-party library, for which the documentation states that I can use pInvoke or create an interop library and use COM.假设我正在访问第三方库,其文档说明我可以使用 pInvoke 或创建互操作库并使用 COM。 What is the difference between these two techniques, and why might I choose one over the other?这两种技术有什么区别,为什么我可以选择一种而不是另一种?

P/Invoke is used to call plain-C APIs (like most of the Win32 API). P/Invoke 用于调用纯 C API(如大多数 Win32 API)。 COM interop is used to call COM objects. COM互操作用于调用COM对象。

You might create a C++ COM wrapper around a C API and then use COM interop to call your wrapper if the number of API calls is relatively high (and you can use the COM wrapper to encapsulate them into just one or two calls).您可以围绕 C API 创建一个 C++ COM 包装器,然后如果 API 调用的数量相对较多,则使用 COM 互操作来调用您的包装器(并且您可以使用 COM 包装器将它们封装到一两个调用中)。 This is because managed-native interop can be relatively expensive and it's good to minimise the number of transitions.这是因为托管本机互操作可能相对昂贵,并且最好尽量减少转换次数。 Though actually I would say using C++/CLI to create the wrapper would probably be a little more friendly for the C# side of thing (looking at SlimDX , for example, which is a C++/CLI wrapper around a COM API (DirectX)).虽然实际上我会说使用 C++/CLI 创建包装器对于 C# 方面可能会更友好一些(例如,查看SlimDX ,它是围绕 COM API (DirectX) 的 C++/CLI 包装器)。

Having said that, unless you have a specific performance problem, I would just use whichever method is more natural for the API you're trying to call: if it's a C API (like the Win32 API is) then use P/Invoke.话虽如此,除非您有特定的性能问题,否则我只会使用对您尝试调用的 API 更自然的方法:如果它是 C API(如 Win32 API),则使用 P/Invoke。 If it's COM-based, then use COM interop.如果它是基于 COM 的,则使用 COM 互操作。

PInvoke uses the dynamic linking mechanism for bringing external code into the executing process. PInvoke 使用动态链接机制将外部代码带入执行过程。 Dynamic linking libraries (DLLs) must have the same target architecture as the calling application, so there is no ability to make cross calls from 64-bit to 32-bit or vice versa.动态链接库 (DLL) 必须与调用应用程序具有相同的目标体系结构,因此无法进行从 64 位到 32 位的交叉调用,反之亦然。 Instead the DLL is mapped into the caller's address space and executed in process.相反,DLL 被映射到调用者的地址空间并在进程中执行。

COM, DCOM, COM+, and ActiveX are all based on interprocess communications libraries, but can sometimes devolve into a simple DLL load. COM、DCOM、COM+ 和 ActiveX 都基于进程间通信库,但有时会演变为简单的 DLL 加载。 COM linked objects are related, but not identical to CORBA objects, but while CORBA evolved its own object locator, the COM implementation is still loosely based on Sun Microsystems RPC and XDR libraries with extensions for the object oriented features of COM. COM 链接对象与 CORBA 对象相关,但不完全相同,但尽管 CORBA 发展了自己的对象定位器,但 COM 实现仍然松散地基于 Sun Microsystems RPC 和 XDR 库,并扩展了 COM 的面向对象特性。 COM objects are referenced not by DLL, but by a GUID which is used to look up the object class and query its interfaces. COM 对象不是由 DLL 引用,而是由用于查找对象类和查询其接口的 GUID 引用。 The object code usually runs in a separate process, and possibly on a separate server.目标代码通常在单独的进程中运行,并且可能在单独的服务器上运行。

Interoperability enables you to preserve and take advantage of existing investments in unmanaged code.互操作性使您能够保留和利用对非托管代码的现有投资。 Code that runs under the control of the common language runtime (CLR) is called managed code, and code that runs outside the CLR is called unmanaged code.在公共语言运行时 (CLR) 控制下运行的代码称为托管代码,在 CLR 之外运行的代码称为非托管代码。 COM, COM+, C++ components, ActiveX components, and Microsoft Win32 API are examples of unmanaged code. COM、COM+、C++ 组件、ActiveX 组件和 Microsoft Win32 API 是非托管代码的示例。

The .NET Framework enables interoperability with unmanaged code through platform invoke (P/Invoke) services, the System.Runtime.InteropServices namespace, C++ interoperability, and COM interoperability (COM interop). .NET Framework 通过平台调用 (P/Invoke) 服务、System.Runtime.InteropServices 命名空间、C++ 互操作性和 COM 互操作性 (COM 互操作) 支持与非托管代码的互操作性。

PInvoke uses the dynamic linking mechanism for bringing external code into the executing process. PInvoke 使用动态链接机制将外部代码带入执行过程。 Dynamic linking libraries (DLLs) must have the same target architecture as the calling application, so there is no ability to make cross calls from 64-bit to 32-bit or vice versa.动态链接库 (DLL) 必须与调用应用程序具有相同的目标体系结构,因此无法进行从 64 位到 32 位的交叉调用,反之亦然。 Instead the DLL is mapped into the caller's address space and executed in process.相反,DLL 被映射到调用者的地址空间并在进程中执行。

COM, DCOM, COM+, and ActiveX are all based on interprocess communications libraries, but sometimes devolve into a simple DLL load. COM、DCOM、COM+ 和 ActiveX 都基于进程间通信库,但有时会演变为简单的 DLL 加载。 COM linked objects are related, but not identical to CORBA objects, but while CORBA evolved its own object locator, the COM implementation is still loosely based on Sun Microsystems RPC and XDR libraries with extensions for the object oriented features of COM. COM 链接对象与 CORBA 对象相关,但不完全相同,但尽管 CORBA 发展了自己的对象定位器,但 COM 实现仍然松散地基于 Sun Microsystems RPC 和 XDR 库,并扩展了 COM 的面向对象特性。 COM objects are referenced not by DLL, but by a GUID which is used to look up the object class and query its interfaces. COM 对象不是由 DLL 引用,而是由用于查找对象类和查询其接口的 GUID 引用。 The object code usually runs in a separate process, or may be on a separate server.目标代码通常在单独的进程中运行,或者可能在单独的服务器上。

For .NET languages, such as Visual Basic and C#, the prescribed method for interoperating with native components is P/Invoke.对于 .NET 语言,例如 Visual Basic 和 C#,与本机组件互操作的规定方法是 P/Invoke。 Because P/Invoke is supported by the .NET Framework, Visual C++ supports it as well, but Visual C++ also provides its own interoperability support, which is referred to as C++ Interop.由于 .NET Framework 支持 P/Invoke,因此 Visual C++ 也支持它,但 Visual C++ 也提供了自己的互操作性支持,称为 C++ Interop。 C++ Interop is preferred over P/Invoke because P/Invoke is not type-safe. C++ 互操作优于 P/Invoke,因为 P/Invoke 不是类型安全的。 As a result, errors are primarily reported at run time, but C++ Interop also has performance advantages over P/Invoke.因此,错误主要在运行时报告,但 C++ Interop 也比 P/Invoke 具有性能优势。

The data marshaling performed by C++ Interop is the simplest possible form: the parameters are simply copied across the managed/unmanaged boundary in a bitwise fashion; C++ Interop 执行的数据封送是最简单的形式:参数以按位方式简单地跨托管/非托管边界复制; no transformation is performed at all.根本不执行任何转换。 For P/Invoke, this is only true if all parameters are simple, blittable types.对于 P/Invoke,仅当所有参数都是简单的 blittable 类型时才如此。 Otherwise, P/Invoke performs very robust steps to convert each managed parameter to an appropriate native type, and vice versa if the arguments are marked as "out", or "in,out".否则,P/Invoke 执行非常稳健的步骤将每个托管参数转换为适当的本机类型,反之亦然,如果参数被标记为“out”或“in,out”。

In other words, C++ Interop uses the fastest possible method of data marshaling, whereas P/Invoke uses the most robust method.换句话说,C++ Interop 使用最快的数据封送方法,而 P/Invoke 使用最健壮的方法。 This means that C++ Interop (in a fashion typical for C++) provides optimal performance by default, and the programmer is responsible for addressing cases where this behavior is not safe or appropriate.这意味着 C++ 互操作(以 C++ 的典型方式)默认提供最佳性能,并且程序员负责解决此行为不安全或不适当的情况。

C++ Interop therefore requires that data marshaling must be provided explicitly, but the advantage is that the programmer is free to decide what is appropriate, given the nature of the data, and how it is to be used.因此,C++ Interop 要求必须明确提供数据封送处理,但优点是程序员可以根据数据的性质和使用方式自由决定什么是合适的。 Furthermore, although the behavior of P/Invoke data marshaling can be modified at customized to a degree, C++ Interop allows data marshaling to be customized on a call-by-call basis.此外,虽然 P/Invoke 数据编组的行为可以在一定程度上进行自定义修改,但 C++ Interop 允许在逐个调用的基础上自定义数据编组。 This is not possible with P/Invoke.这对于 P/Invoke 是不可能的。

P/Invoke Example below: P/调用示例如下:

using System;
using System.Runtime.InteropServices;

public class Win32 {
     [DllImport("user32.dll", CharSet=CharSet.Auto)]
     public static extern IntPtr MessageBox(int hWnd, String text, 
                     String caption, uint type);
}

public class HelloWorld {
    public static void Main() {
       Win32.MessageBox(0, "Hello World", "Platform Invoke Sample", 0);
    }
}

Com interop example (in C++ that consuming c# code) Com 互操作示例(在使用 C# 代码的 C++ 中)

// ConLoan.cpp : Defines the entry point for the console application.  
#include "stdafx.h"  
#import "..\LoanLib\LoanLib.tlb" raw_interfaces_only  
using namespace LoanLib;  

int main(int argc, char* argv[])  
{  
    HRESULT hr = CoInitialize(NULL);  

    ILoanPtr pILoan(__uuidof(Loan));  

    if (argc < 5)   
    {  
        printf("Usage: ConLoan Balance Rate Term Payment\n");  
        printf("    Either Balance, Rate, Term, or Payment must be 0\n");  
        return -1;  
    }  

    double openingBalance = atof(argv[1]);  
    double rate = atof(argv[2])/100.0;  
    short  term = atoi(argv[3]);  
    double payment = atof(argv[4]);  

    pILoan->put_OpeningBalance(openingBalance);  
    pILoan->put_Rate(rate);  
    pILoan->put_Term(term);  
    pILoan->put_Payment(payment);  

    if (openingBalance == 0.00)   
         pILoan->ComputeOpeningBalance(&openingBalance);  
    if (rate == 0.00) pILoan->ComputeRate(&rate);  
    if (term == 0) pILoan->ComputeTerm(&term);  
    if (payment == 0.00) pILoan->ComputePayment(&payment);  

    printf("Balance = %.2f\n", openingBalance);  
    printf("Rate    = %.1f%%\n", rate*100);  
    printf("Term    = %.2i\n", term);  
    printf("Payment = %.2f\n", payment);  

    VARIANT_BOOL MorePmts;  
    double Balance = 0.0;  
    double Principal = 0.0;  
    double Interest = 0.0;  

    printf("%4s%10s%12s%10s%12s\n", "Nbr", "Payment", "Principal", "Interest", "Balance");  
    printf("%4s%10s%12s%10s%12s\n", "---", "-------", "---------",   
"--------", "-------");  

    pILoan->GetFirstPmtDistribution(payment, &Balance, &Principal, &Interest, &MorePmts);  

    for (short PmtNbr = 1; MorePmts; PmtNbr++)   
    {  
        printf("%4i%10.2f%12.2f%10.2f%12.2f\n",  
        PmtNbr, payment, Principal, Interest, Balance);  

        pILoan->GetNextPmtDistribution(payment, &Balance, &Principal, &Interest, &MorePmts);   
    }  

    CoUninitialize();  
    return 0;  
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 AxInterop 和 Interop 有什么区别? - What is the difference between AxInterop and Interop? .NET互操作层和COM之间会发生什么? - What happens between the .NET interop layer and COM? Interop和RCW(运行时可调用包装器)有什么区别? - What is the difference between an Interop and a RCW (Runtime Callable Wrapper)? 之间有什么区别<COM Reference>和<Reference>在.csproj 中? - What is the difference between <COM Reference> and <Reference> in .csproj? .NET组件和COM组件之间有什么区别 - What is the Difference between .NET components and COM Components COM Interop 的泛型集合有哪些替代方案? - What are alternatives to generic collections for COM Interop? COM字符串(BSTR)和.NET字符串之间有什么区别? - What is the difference between a COM string (BSTR) and a .NET string? Interop Outlook 和 Outlook Object 库之间的区别 - Difference between Interop Outlook and Outlook Object Library COM Interop问题,开发机器和客户端机器之间的行为不一致 - COM Interop issues, inconsistent behavior between dev machine and client machine MethodImplAttribute(InternalCall,Runtime)对COM Interop接口的方法做了什么? - What does MethodImplAttribute(InternalCall, Runtime) do for methods of COM Interop interfaces?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM