在C ++中使用COM dll

时间:2016-01-07 21:36:45

标签: c++ dll com

我需要使用COM库中的方法。我已导入.dll并复制了.tlh文件。我是C ++和COM的新手,在描述问题时可能会出现明显的错误。我正在尝试识别接口和方法,并学习如何实现它们。我相信“Open”,“Close”,“GetFileName”,“GetCreatorID”等都是方法,而IXRawfile是一个接口。这是.tlh

namespace MSFileReaderLib {

//
// Forward references and typedefs
//

struct __declspec(uuid("f0c5f3e3-4f2a-443e-a74d-0aabe3237494"))
/* LIBID */ __MSFileReaderLib;
enum __MIDL___MIDL_itf_XRawfile2_0000_0000_0001;
enum __MIDL___MIDL_itf_XRawfile2_0000_0000_0002;
enum __MIDL___MIDL_itf_XRawfile2_0000_0000_0003;
enum __MIDL___MIDL_itf_XRawfile2_0000_0000_0004;
enum MS_PacketTypes;
enum MS_Polarity;
enum MS_ScanData;
enum MS_Dep;
enum MS_Wideband;
enum MS_SourceCID;
enum MS_SourceCIDType;
enum MS_MSOrder;
enum MS_ScanType;
enum MS_TurboScan;
enum MS_IonizationMode;
enum MS_Corona;
enum MS_Detector;
enum MS_PrecursorEnergy;
enum MS_Multiplex;
enum MS_Param_A;
enum MS_Param_B;
enum MS_Param_F;
enum MS_Param_K;
enum MS_Param_R;
enum MS_Param_V;
enum MS_Activations;
struct MS_FullMSOrderPrecursorInfo;
struct MS_MassRange;
struct MS_ScanEvent;
struct MS_ScanIndex;
struct MS_ScanIndex64;
struct MS_UVScanIndex;
struct MS_DataPeak;
struct MS_PrecursorInfo;
struct __declspec(uuid("11b488a0-69b1-41fc-a660-fe8df2a31f5b"))
/* dual interface */ IXRawfile;
struct __declspec(uuid("55a25ff7-f437-471f-909a-d7f2b5930805"))
/* dual interface */ IXRawfile2;
struct __declspec(uuid("19a00b1e-1559-42b1-9a46-08a5e599edee"))
/* dual interface */ IXRawfile3;
struct __declspec(uuid("e7cf6760-11cd-4260-b5b0-fce2ad97547b"))
/* dual interface */ IXRawfile4;
struct __declspec(uuid("06f53853-e43c-4f30-9e5f-d1b3668f0c3c"))
/* dual interface */ IXRawfile5;
struct __declspec(uuid("55ea38b7-5419-4be4-9198-3e4d78e64632"))
/* dual interface */ IXVirMS;
enum MS_DataTypes;
struct __declspec(uuid("7ff032a3-fb2a-46ef-a579-039da67c0aaa"))
/* dual interface */ IXVirMS64;
struct MS_ScanDataStruct;
struct __declspec(uuid("796cb3fe-c696-4afe-b719-18246f38a740"))
/* dual interface */ IXVirUV;
struct /* coclass */ MSFileReader_XRawfile;
struct /* coclass */ MSFileReader_XVirMS;
struct /* coclass */ MSFileReader_XVirUV;

//
// Smart pointer typedef declarations
//

_COM_SMARTPTR_TYPEDEF(IXRawfile, __uuidof(IXRawfile));
_COM_SMARTPTR_TYPEDEF(IXRawfile2, __uuidof(IXRawfile2));
_COM_SMARTPTR_TYPEDEF(IXRawfile3, __uuidof(IXRawfile3));
_COM_SMARTPTR_TYPEDEF(IXRawfile4, __uuidof(IXRawfile4));
_COM_SMARTPTR_TYPEDEF(IXRawfile5, __uuidof(IXRawfile5));
_COM_SMARTPTR_TYPEDEF(IXVirMS, __uuidof(IXVirMS));
_COM_SMARTPTR_TYPEDEF(IXVirMS64, __uuidof(IXVirMS64));
_COM_SMARTPTR_TYPEDEF(IXVirUV, __uuidof(IXVirUV));

//
// Type library items
//

enum __MIDL___MIDL_itf_XRawfile2_0000_0000_0001
{
    MS_TRAILER_NOT_AVAILABLE = -1
};

接下来是更多的调查员,直到我这样做。

#pragma pack(pop)

struct __declspec(uuid("11b488a0-69b1-41fc-a660-fe8df2a31f5b"))
IXRawfile : IDispatch
{
    //
    // Wrapper methods for error-handling
    //

    HRESULT Open (
        _bstr_t szFileName );
    HRESULT Close ( );
    HRESULT GetFileName (
        BSTR * pbstrFileName );
    HRESULT GetCreatorID (
        BSTR * pbstrCreatorID );
    HRESULT GetVersionNumber (
        long * pnVersion );
    HRESULT GetCreationDate (
        DATE * pCreationDate );
    HRESULT IsError (
        long * pbIsError );

代码继续这样,然后添加以下内容。

 //
    // Raw methods provided by interface
    //

      virtual HRESULT __stdcall raw_Open (
        BSTR szFileName ) = 0;
      virtual HRESULT __stdcall raw_Close ( ) = 0;
      virtual HRESULT __stdcall raw_GetFileName (
        BSTR * pbstrFileName ) = 0;
      virtual HRESULT __stdcall raw_GetCreatorID (
        BSTR * pbstrCreatorID ) = 0;
      virtual HRESULT __stdcall raw_GetVersionNumber (
        long * pnVersion ) = 0;
      virtual HRESULT __stdcall raw_GetCreationDate (
        DATE * pCreationDate ) = 0;
      virtual HRESULT __stdcall raw_IsError (
        long * pbIsError ) = 0;

在许多类似的陈述之后,该程序与下一个陈述类似。

struct __declspec(uuid("55a25ff7-f437-471f-909a-d7f2b5930805"))
IXRawfile2 : IXRawfile
{
    //
    // Wrapper methods for error-handling
    //

    HRESULT GetLabelData (
        VARIANT * pvarLabels,
        VARIANT * pvarFlags,
        long * pnScanNumber );
    HRESULT GetNoiseData (
        VARIANT * pvarNoisePacket,
        long * pnScanNumber );

我使用以下页面来实现这一目标http://www.codeproject.com/Questions/202460/using-COM-dll-in-a-c-console-application,但我无法理解如何实现作者的第二个解决方案。我该怎么办?

1 个答案:

答案 0 :(得分:0)

您的程序是否正在尝试创建在#import的DLL中定义的COM对象的实例?这很容易。这是一个粗略的模式。假设你有some.dll包含一个名为MyObject的类,它实现了IMyInterface。

#import "some.dll"

void main()
{
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

    // if you use smart pointers, it's best to have an
    // inner scope to ensure that all your objects are
    // released before calling CoUninitialize
    {
        IMyInterfacePtr o;
        o.CreateInstance(CLSID_MyObject);
        o->SomeMethod();
    }

    CoUninitialize();
}

除非#import语句中包含其他属性,否则#import应为您创建所有这些工件。具体做法是:

  • COM库中的每个接口都将为其创建一个智能指针。此智能指针只是附加Ptr的接口的名称。在上面的代码中,IMyInterfacePtrIMyInterface引用的智能指针。这些智能指针执行所有必要的AddRef / Release / QueryInterface工作,并提供CreateInstance来创建类的实例并获取对其上的接口的引用。
  • COM库中项目的LIBID,IID和CLSID将使用LIBID__MyLibIID_IMyInterfaceCLSID_MyConcreteObject形式的全局变量自动公开。这使CreateInstance电话变得容易。
  • 除非在raw_interfaces_only语句中使用#import,否则接口的方法将自动包含在某些代码中,这些代码会在异常情况下抛出_com_error。如果没有raw_interfaces_only,您将获得大多数方法的两种形式 - 一种只包含方法名称,另一种方法名称以raw_为前缀。 raw_表单不会抛出任何异常并使用原始COM类型(例如BSTR,VARIANT)。非原始表单抛出异常并使用一些高级类型(_bstr_t,variant_t)。我通常喜欢使用非原始表单,因为这意味着我必须做更少的错误检查。但我也喜欢异常,许多其他C ++开发人员都没有。