How to declare COM interface with properties in C++

0

I'm trying to call a registered COM interface (Inproc dll) in an Eclipse C++ environment (MinGW GCC toolchain). I therefore don't believe that I can simply import the dll typelib the way I typically would in Visual C++. I'm trying to define the interface myself to simplify the function calls rather than using Invoke.

The IDL for the interface out of oleview looks like:

  uuid(9293C753-B073-11D2-BD89-0060978EEB9C),
  helpstring("IXSequence Interface"),
  dual
]
dispinterface IXSequence {
    properties:
    methods:
        [id(0x00000001), helpstring("method Close")]
        void Close();
        [id(0x00000002), helpstring("method New")]
        void New();
        [id(0x00000003), helpstring("method Open")]
        void Open(
                        BSTR FileName, 
                        long ReadOnly);
        [id(0x00000004), helpstring("method Save")]
        void Save(
                        BSTR UserName, 
                        BSTR Comment, 
                        long Overwrite);
        [id(0x00000005), helpstring("method SaveAs")]
        void SaveAs(
                        BSTR FileName, 
                        BSTR UserName, 
                        BSTR Comment, 
                        long Overwrite);
        [id(0x00000006), propget, helpstring("property Header")]
        VARIANT Header();
        [id(0x00000007), propget, helpstring("property AuditDataCollection")]
        VARIANT AuditDataCollection();
        [id(0x00000008), propget, helpstring("property Samples")]
        VARIANT Samples();
        [id(0x00000009), propget, helpstring("property BracketType")]
        XBracketTypes BracketType();
        [id(0x00000009), propput, helpstring("property BracketType")]
        void BracketType([in] XBracketTypes rhs);
        [id(0x0000000a), propget, helpstring("property UserLabel")]
        BSTR UserLabel(short Index);
        [id(0x0000000a), propput, helpstring("property UserLabel")]
        void UserLabel(
                        short Index, 
                        [in] BSTR rhs);
        [id(0x0000000b), propget, helpstring("property TrayConfiguration")]
        BSTR TrayConfiguration();
        [id(0x0000000b), propput, helpstring("property TrayConfiguration")]
        void TrayConfiguration([in] BSTR rhs);
        [id(0x0000000c), propget, helpstring("property FileName")]
        BSTR FileName();
        [id(0x0000000d), propget, helpstring("property NewFile")]
        long NewFile();
};

I've attempted to define the interface in my own header file like this:

const GUID CLSID_XcalFiles = { 0x9293C754, 0xB073, 0x11D2, {0xBD, 0x89, 0x00, 0x60, 0x97, 0x8E, 0xEB, 0x9C } };
const IID IID_IXSequence = { 0x9293C753, 0xB073, 0x11D2, {0xBD, 0x89, 0x00, 0x60, 0x97, 0x8E, 0xEB, 0x9C } };

typedef enum {
    XUnspecified = 0,
    XOverlapped = 1,
    XNonBracketed = 2,
    XNonOverlapped = 3,
    XOpen = 4
} XBracketTypes;

enum XSampleTypes
{
    XSampleUnknown = 0,
    XSampleBlank = 1,
    XSampleQC = 2,
    XSampleStdClear = 3,
    XSampleStdUpdate = 4,
    XSampleStdBracket = 5,
    XSampleStdBracketStart = 6,
    XSampleStdBracketEnd = 7,
    XSampleProgram = 8,
    XSampleNumbersOfDifferentTypes = 9
};

DECLARE_INTERFACE_(IXSequence, IDispatch)
{
//methods
    STDMETHOD_(void, Close)(THIS)PURE;
    STDMETHOD_(void, New)(THIS)PURE;
    STDMETHOD_(void, Open)(THIS_ BSTR FileName, long ReadOnly)PURE;
    STDMETHOD_(void, Save)(THIS_ BSTR UserName, BSTR Comment, long Overwrite)PURE;
    STDMETHOD_(void, SaveAs)(THIS_ BSTR FileName, BSTR UserName, BSTR Comment, long Overwrite)PURE;
    STDMETHOD_(VARIANT, GetHeader)(THIS)PURE;
    STDMETHOD_(VARIANT, GetAuditDataCollection)(THIS)PURE;
    STDMETHOD_(VARIANT, GetSamples)(THIS)PURE;
//properties
    STDMETHOD_(XBracketTypes, BracketType)(THIS)PURE;
    STDMETHOD_(void, BracketType)(THIS_ XBracketTypes rhs)PURE;
    STDMETHOD_(BSTR, UserLabel)(THIS_ short Index)PURE;
    STDMETHOD_(void, UserLabel)(THIS_ short Index, BSTR rhs)PURE;
    STDMETHOD_(BSTR, TrayConfiguration)(THIS)PURE;
    STDMETHOD_(void, TrayConfiguration)(THIS_ BSTR rhs)PURE;
    STDMETHOD_(BSTR, FileName)(THIS)PURE;
    STDMETHOD_(long, NewFile)(THIS)PURE;

};

This appears to work well for the method calls but not for the properties. When I attempt to call any of the property functions, I get access violations. It does however seem to work if I use something like

STDMETHOD(GetBracketType)(THIS_ XBracketTypes* rhs)PURE;

Does that make sense? Is there a better way to declare the properties for the COM interface so that I can use them like normal properties?

c++
interface
com
idispatch
asked on Stack Overflow Nov 5, 2019 by forother

1 Answer

0

Usually, C++ interfaces are something like:

STDMETHOD(get_BracketType)(BracketType* BType);

STDMETHOD(put_BrackedType)(BracketType Btype);

Properties are generally going to have HRESULT return types... just like methods. They'll have a get_ or put_ prefix in front of the property name.

Not sure how the Eclipse C++ environment does this.

answered on Stack Overflow Nov 5, 2019 by Joseph Willcoxson

User contributions licensed under CC BY-SA 3.0