当输出参数是类时,如何在C ++中调用COM方法?

时间:2014-02-07 18:16:26

标签: c# c++ dll com mfc

背景

我是一名C#开发人员,几乎没有使用过C ++的经验,而且只有一点点使用COM。我的同事是一名C ++开发人员,几乎没有.Net的经验,而且很少有COM。我们试图让他的C ++ MFC应用程序使用我在C#on .Net 3.5上编写的DLL。

我主要关注本教程:http://www.codeproject.com/Articles/12673/Calling-Managed-NET-C-COM-Objects-from-Unmanaged-C

但是,我找不到任何返回对象而不是简单类型的COM接口示例。

DLL

在程序集级别,我有ComVisible(false),因为真正的DLL中有很多类不会从C ++中使用。这让我可以在我希望在COM中看到的类和接口上使用ComVisible(true)

using System;
using System.Reflection;
using System.Runtime.InteropServices;

[assembly: ComVisible( false )]
[assembly: Guid( "59db8b2b-572d-42fc-83ae-36fe1a97695f" )]
[assembly: AssemblyVersion( "1.0.0.0" )]
[assembly: AssemblyFileVersion( "1.0.0.0" )]

namespace ComTest
{
    [Guid( "9600F16D-2ECA-446C-83C9-B15FD472D12D" )]
    [ComVisible( true )]
    public interface ITestClass
    {
        ISerialInfo GetSerialInfo( string serial );
    }

    [Guid( "3C63AF8C-4730-4526-94C9-D8AA6805962A" )]
    [ComVisible( true )]
    [ClassInterface( ClassInterfaceType.None )]
    public class TestClass : ITestClass
    {
        public ISerialInfo GetSerialInfo( string serial )
        {
            //Other properties excluded for brevity.
            return new SerialInfo
            {
                SerialNumber = serial
            };
        }
    }

    [Guid( "F2885515-EEE8-49B1-B795-B92955EFEF0D" )]
    [ComVisible( true )]
    public interface ISerialInfo
    {
        string BomRevision { get; set; }
        string InteroperationStep { get; set; }
        bool IsValid { get; set; }
        string Job { get; set; }
        string JobSalesOrder { get; set; }
        int JobSalesOrderLine { get; set; }
        string MaterialStatus { get; set; }
        int OperationSequence { get; set; }
        string Organization { get; set; }
        string ParentSerialNumber { get; set; }
        string PartNumber { get; set; }
        string SerialNumber { get; set; }
        string State { get; set; }
    }

    [Guid( "D60020F1-823D-497E-A91D-427AEA1195C6" )]
    [ComVisible( true )]
    [ClassInterface( ClassInterfaceType.None )]
    public class SerialInfo : ISerialInfo
    {
        public bool IsValid { get; set; }
        public string SerialNumber { get; set; }
        public string Organization { get; set; }
        public string PartNumber { get; set; }
        public string Job { get; set; }
        public string BomRevision { get; set; }
        public string JobSalesOrder { get; set; }
        public int JobSalesOrderLine { get; set; }
        public int OperationSequence { get; set; }
        public string InteroperationStep { get; set; }
        public string ParentSerialNumber { get; set; }
        public string MaterialStatus { get; set; }
        public string State { get; set; }
    }
}

COM注册

我使用以下批处理文件为COM注册DLL并生成TLB文件。

"C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\gacutil" /i ComTest.dll
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm" ComTest.dll /tlb:ComTest.tlb

TLH文件的片段

virtual HRESULT __stdcall GetSerialInfo (
        /*[in]*/ BSTR serial,
        /*[out,retval]*/ struct ISerialInfo * * pRetVal ) = 0;

MFC应用程序

我不知道该方法的输出参数传递什么。我尝试了几件事,我可以让它构建,但不能运行。我不知道是否必须实例化一个具体的TestClass然后将其转换为接口并传入指向它的指针,或者什么。我在这里不知所措。我已经做了很多谷歌搜索,但找不到任何示例显示COM返回的不仅仅是字符串或整数。如果我的方法返回一个int,我可以让它工作得很好。

我已经排除了所有样板代码。

#import "C:\\Users\\Glazed\\Documents\\Visual Studio 2012\\Projects\\ComTest\\ComTest\\bin\\Debug\\ComTest.tlb" named_guids raw_interfaces_only

CMainFrame::CMainFrame()
{
    CoInitialize(NULL);

    ComTest::ITestClassPtr testClassPtr;

    HRESULT hRes = testClassPtr.CreateInstance(ComTest::CLSID_TestClass);

    if (hRes == S_OK)
    {
        //What goes here to initialize an entity to pass into the following method

        testClassPtr->GetSerialInfo( L"TE-006",  );
    }

    CoUninitialize();
}

1 个答案:

答案 0 :(得分:1)

您需要一个指向该对象的指针。通过#import看起来有很多包装,所以看起来合适的类是ComTest::ISerialInfoPtr

if (hRes == S_OK)
{
    ComTest::ISerialInfoPtr pInfo;
    hRes = testClassPtr->GetSerialInfo( L"TE-006", &pInfo);
}