【问题标题】:C# COM Interop: exposing function with a managed object as parameterC# COM 互操作:以托管对象作为参数公开函数
【发布时间】:2013-06-22 08:37:47
【问题描述】:

我通过了tutorial of C# COM INterop。执行链接中给出的演示示例成功运行!理解那里的每一个陈述,它们的含义。 并遇到了the equivalent data types for c# objects.

除了 Adam Nathan 的 .NET 和 COM 互操作性以及 Nishant Shivakumar 的 CCLI in Action 之外,我找不到任何好书(包括有关 C# COM 互操作和从本机 C++ 调用 COM 组件的示例)。我在注册程序集和其他东西方面没有问题,但在 COM 语法方面遇到了问题。 在解释我的代码之前,我想了解VARIANT 是什么。为什么会在那里?

这是我的情况,我有一个 C# 类如下:

using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
namespace ManagedDLL
{
    // Interface declaration.
    [ComVisible(true), Guid("3265C537-E149-4559-B4E1-DBE334927DFA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface ICalculator
    {
        int Add(int Number1, int Number2);
        int Subtract(Subtraction sb);
    };
    // Interface implementation.
    [ComVisible(true), Guid("0F50D3BE-CEEA-4C57-9882-4A609C7BB36C")]
    public class ManagedClass : ICalculator
    {
        private int a, b;
        public int Add(int Number1, int Number2)
        {
            return Number1 + Number2;
        }
        public int Subtract(Subtraction sub)
        {
            int a = 10, b = 3;
            return sub.SubtractTwoNumbers(a, b);
        }

    }
    [ComVisible(true)]
    [Guid("C718EDDE-541C-4D15-B7EA-0533AB11A839")]
    [ClassInterface(ClassInterfaceType.None)]
    public class Subtraction
    {
        public int SubtractTwoNumbers(int a, int b)
        {
            return a - b;
        }

    }
}

导入tlb文件后得到.tlh文件如下:

#pragma once
#pragma pack(push, 8)

#include <comdef.h>

namespace ManagedDLL {

//
// Forward references and typedefs
//

struct __declspec(uuid("4e5098b7-4e51-45e5-a705-a7e3c51e2a80"))
/* LIBID */ __ManagedDLL;
struct __declspec(uuid("3265c537-e149-4559-b4e1-dbe334927dfa"))
/* interface */ ICalculator;
struct /* coclass */ ManagedClass;
struct /* coclass */ Subtraction;
struct __declspec(uuid("c8e9181c-f064-3ec1-869e-042c6fdd3e46"))
/* dual interface */ _ManagedClass;

//
// Smart pointer typedef declarations
//

_COM_SMARTPTR_TYPEDEF(ICalculator, __uuidof(ICalculator));
_COM_SMARTPTR_TYPEDEF(_ManagedClass, __uuidof(_ManagedClass));

//
// Type library items
//

struct __declspec(uuid("3265c537-e149-4559-b4e1-dbe334927dfa"))
ICalculator : IUnknown
{
    //
    // Raw methods provided by interface
    //

      virtual HRESULT __stdcall Add (
        /*[in]*/ long Number1,
        /*[in]*/ long Number2,
        /*[out,retval]*/ long * pRetVal ) = 0;
      virtual HRESULT __stdcall Subtract (
        /*[in]*/ struct _Object * sb,
        /*[out,retval]*/ long * pRetVal ) = 0;
};

struct __declspec(uuid("0f50d3be-ceea-4c57-9882-4a609c7bb36c"))
ManagedClass;
    // [ default ] interface _ManagedClass
    // interface _Object
    // interface ICalculator

struct __declspec(uuid("c718edde-541c-4d15-b7ea-0533ab11a839"))
Subtraction;
    // [ default ] interface _Object

struct __declspec(uuid("c8e9181c-f064-3ec1-869e-042c6fdd3e46"))
_ManagedClass : IDispatch
{};

//
// Named GUID constants initializations
//

extern "C" const GUID __declspec(selectany) LIBID_ManagedDLL =
    {0x4e5098b7,0x4e51,0x45e5,{0xa7,0x05,0xa7,0xe3,0xc5,0x1e,0x2a,0x80}};
extern "C" const GUID __declspec(selectany) IID_ICalculator =
    {0x3265c537,0xe149,0x4559,{0xb4,0xe1,0xdb,0xe3,0x34,0x92,0x7d,0xfa}};
extern "C" const GUID __declspec(selectany) CLSID_ManagedClass =
    {0x0f50d3be,0xceea,0x4c57,{0x98,0x82,0x4a,0x60,0x9c,0x7b,0xb3,0x6c}};
extern "C" const GUID __declspec(selectany) CLSID_Subtraction =
    {0xc718edde,0x541c,0x4d15,{0xb7,0xea,0x05,0x33,0xab,0x11,0xa8,0x39}};
extern "C" const GUID __declspec(selectany) IID__ManagedClass =
    {0xc8e9181c,0xf064,0x3ec1,{0x86,0x9e,0x04,0x2c,0x6f,0xdd,0x3e,0x46}};

} // namespace ManagedDLL

#pragma pack(pop)

最后这是我的原生 C++ 应用程序:

HRESULT hr = CoInitialize(NULL);
ManagedDLL::ICalculatorPtr ptrInterface(__uuidof(ManagedDLL::ManagedClass));
IUnknown* pUnk=NULL;
hr=CoCreateInstance(__uuidof(ManagedDLL::Subtraction), NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)pUnk);
long lResult;
ptrInterface->Subtract(pUnk, &lResult); //what should be written instead of pUnk, because it expects a _Object* as evident in the tlh file
return  lResult;

问题很多:

  1. 如何访问接口中的Subtract方法?我们应该如何实例化 Subtraction 类,其对象应该作为 Subtract 方法中的参数传递?

  2. 如何收集返回 COM 类作为返回类型的函数的值?

  3. IUnknownIDispatch 是什么?

  4. 最重要的是,为什么在 COM .tlh 文件中创建 _Object* 作为参数而不是 Subtraction* 作为参数?

【问题讨论】:

  • 这是您要询问的基本 C++ COM 样板代码。书籍将是找到这些问题答案的更好地方。

标签: c# c++ pointers com variant


【解决方案1】:

您提出的问题是关于 COM 的经典基本问题,可能需要一本小书才能回答。我建议您获取有关 COM 的教程或书籍,以加快速度。在您了解 COM 基础知识之前,您不会了解互操作。从那里开始,然后完成更难的事情。

了解所有涉及的问题需要一些认真的时间,所以不要着急!

这是一个开始的地方: http://msdn.microsoft.com/en-us/library/727z646z(v=vs.80).aspx

【讨论】:

  • 嘿@ed 你能告诉我如何订阅在本机 c++ 中公开为 COM 的 c# 事件。我搜索了 Adam Nathan 的 .NET 和 COM 书籍,但得到了 VB COM 客户端代码。我想要 c++ 示例。我开始了解 Advise 和 Unadvise 关键字以及 IConnectionPointPtr。研究了这些概念,但找不到任何例子!有吗?
猜你喜欢
  • 2012-07-19
  • 2015-06-29
  • 1970-01-01
  • 2013-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多