Search code examples
c++comatl

How to pass ATL com class object as paramater to COM


Like this thread, but when I pass a string into the method, the string in com class is wrong, here is the code:

com server - Com.idl:

interface IParamClass : IUnknown
{
    [] HRESULT SetString([in] BSTR str);
}

interface IMyClass : IUnknown
{
    [] HRESULT PassComClassAsParam([in] IParamClass* parm);
}

ParamClass.cpp

class ATL_NO_VTABLE CParamClass : ...
{
...
public:
    BSTR m_str;

    STDMETHOD(SetString)(BSTR str);
};

STDMETHODIMP CParamClass::SetString(BSTR str)
{
    m_str = str;
    return S_OK;
}

MyClass.cpp:

STDMETHODIMP CMyClass::PassComClassAsParam( IParamClass* param)
{
    CParamClass *obj = (CParamClass*)param;
    BSTR str = obj->m_str;    //debugging here, is wrong string
...
}

C# Client:

MyClass myobj = new MyClass();
ParamClass param = new ParamClass();
param.SetString("Test String!");
myobj.PassComClassAsParam(param);

Solution

  • You have to make a copy of string argument here since you are not controlling the lifetime of the value:

    STDMETHODIMP CParamClass::SetString(BSTR str)
    {
        m_str = str; // str is valid here, but you don't know when
                     // the value is destroyed later
        return S_OK;
    }
    

    By the time you use the value through m_str variable, the string is already freed and destroyed, hence you see it "wrong".

    The typical solution is:

    class ATL_NO_VTABLE CParamClass : ...
    {
    ...
    public:
        CComBSTR m_str; // <<--- Note CComBSTR
    
        STDMETHOD(SetString)(BSTR str);
    };
    
    STDMETHODIMP CParamClass::SetString(BSTR str)
    {
        m_str = str;
        return S_OK;
    }