我定义了一个COM接口IXManageInfoBase,并有对应的事件接口DXManageInfoBaseEvents
interface IXManageInfoBase : IUnknown{
typedef struct _CLIENT_INFO{
DWORD dwIpAddr;
USHORT usPort;
[string] wchar_t* pwszMAC;
[string] wchar_t* pwszComputerName;
}CLIENT_INFO; [, helpstring("method GetXXXX")] HRESULT GetXXXX([in] CLIENT_INFO* pClient);
};library sdcsrvmLib
{
        ......
dispinterface DXManageInfoBaseEvents
{
properties:
methods:
[id(1), helpstring("method OnClientChanged")] HRESULT OnClientChanged([in] CLIENT_INFO* pclient);
};
        .......
coclass XManageInfoBase
{
[default] interface IXManageInfoBase;
[default, source] dispinterface DXManageInfoBaseEvents;
};
};GetXXXX和OnClientChanged的函数参数类型都是CLIENT_INFO*
GetXXXX函数调用正常,
但事件接口中的OnClientChanged函数中使用CLIENT_INFO*时碰到几个问题:
1, 以下代码是MFC自动为事件接口对象生成的代码,但在编译的时候,编译器警告说会把avarParams[0] = pclient;强制转为BOOL型
2.  我把代码改为如下: avarParams[0] = (BYTE*)pclient;  编译没有警告了,但在客户端被传递过去的只是一个字节
请问我该如何修改才能把CLIENT_INFO的完整结构传递过去?
#pragma once
template<class T>
class CProxyDXManageInfoBaseEvents :
public IConnectionPointImpl<T, &__uuidof(DXManageInfoBaseEvents)>
{
public:
HRESULT Fire_OnClientChanged( SDC_EVENT_ACTION sea,  SDC_CLIENT_INFO * pclient)
{
HRESULT hr = S_OK;
T * pThis = static_cast<T *>(this);
int cConnections = m_vec.GetSize(); for (int iConnection = 0; iConnection < cConnections; iConnection++)
{
pThis->Lock();
CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
pThis->Unlock(); IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p); if (pConnection)
{
CComVariant avarParams[2];
avarParams[1] = sea;
avarParams[0] = pclient;
CComVariant varResult; DISPPARAMS params = { avarParams, NULL, 2, 0 };
hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);
}
}
return hr;
}
};

解决方案 »

  1.   

    在IDL定义中,OnClientChanged明明只有一个参数,但是Fire_OnClientChanged却有两个参数,应该是你修改过IDL定义而没有更新CProxy...的函数参数。
      

  2.   

    为了对比明显一点,所以特地把不要的参数去掉了,
    编译时顺利通过的,而且事件函数触发顺利,但就是传递过去的参数不对
    COM客户端调用COM服务器的接口这样写没问题,但事件回调这样写就有问题,不知道为什么?再重贴一边后一部分#pragma once
    template<class T>
    class CProxyDXManageInfoBaseEvents :
    public IConnectionPointImpl<T, &__uuidof(DXManageInfoBaseEvents)>
    {
    public:
    HRESULT Fire_OnClientChanged(SDC_CLIENT_INFO * pclient)
    {
    HRESULT hr = S_OK;
    T * pThis = static_cast<T *>(this);
    int cConnections = m_vec.GetSize(); for (int iConnection = 0; iConnection < cConnections; iConnection++)
    {
    pThis->Lock();
    CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
    pThis->Unlock(); IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p); if (pConnection)
    {
    CComVariant avarParams[1];
    avarParams[0] = pclient;
    CComVariant varResult; DISPPARAMS params = { avarParams, NULL, 1, 0 };
    hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);
    }
    }
    return hr;
    }
    };
      

  3.   

    问题在avarParams[0] = pclient;这句,可以跟踪看看如果编译通过,构造出来的VARIANT是哪种变量类型。
    由于你传递的指针是用户类型指针,当连接点客户端被调用时,VARIANT参数没有正确地转换成你需要的指针类型,后果是难以预料的。
      

  4.   

    To: jameshooo
    谢谢, VARIANT好像是被强制转换成了BOOL型,
    avarParams[0] = (BYTE*)pclient;  将其强制转化为BYTE*型,还是不对,
    问题是看了下CComVariant的赋值函数,只有对应几个基本类型的,我无法写成avarParams[0] = (CLIENT_INFO*)pclient,编译通不过的
    请问CComVariant中的类型应该设成什么类型才能正确传递参数。To: yjgx007
    请问“包装在Variant变量中传递.”是什么意思,能不能说的详细点,谢谢。
      

  5.   

    CLIENT_INFO最好是IDispatch接口的派生类, 举例:class CLIENT_INFO : public IDispatch
    {
    };传递时,
    CLIENT_INFO ci;
    VARIANT var;
    var.vt = VT_DISPATCH;
    var.pdispVal= &ci;接口定义:[id(1), helpstring("method OnClientChanged")] HRESULT OnClientChanged([in] VARIANT* pclient);
    用非标准的COM接口作参数只能产生未遇料到的错误 .
      

  6.   

    使用 avarParams[0] = (BYTE*)pclient; 是可以的,它会使用VT_UI1|VT_BYREF类型,并且在pbVal中保存指针,问题在于连接点被调用时的反向转换可能不成功。你可以在Invoke处设置断点,然后跟踪进去,看看IDispEventImpl中(如果是MFC,它有其它的封装形式)是如何反向转换VARIANT的,也许在解析VT_UI1|VT_BYREF时出的问题。还有其它替代方案,比如不使用自定义结构,而是用SAFEARRAY或者BSTR都能解决你的问题。
      

  7.   

    问题关键在于他希望pclient到底是什么类型,是UT1么?看起来不像
      

  8.   

    COM不熟,一知半解,
    pclient是我自己定义的一个结构指针,
    不清楚是服务器端还是客户端把数据给截留了,
    只是奇怪的是如果是一个普通接口的方法的话,参数传递是没问题的,搞不清楚了
    不过采用了一个笨办法,先发问题给对应过去了,
    感谢楼上各位的帮忙了。~~