我的IDL文件如下(部分):[
uuid(54035A23-B92A-4239-B401-6022867DF53B),
helpstring("_ICashCodeEvents Interface")
]
dispinterface _ICashCodeEvents
{
properties:
methods:
[id(1), helpstring("method CashPolled")] HRESULT CashPolled([in]long lMoney);
[id(2), helpstring("method ReturnStatus")] HRESULT ReturnStatus([in]short sCode,[out,retval]boolean *pboolCancel);
}; [
uuid(F2C949F7-8203-435D-834D-9A0A3F60715F),
helpstring("CashCode Class")
]
coclass CashCode
{
[default] interface ICashCode;
[default, source] dispinterface _ICashCodeEvents;
};
使用"连接点实现向导"通过CProxy_ICashCodeEvents类实现的连接点,CProxy_ICashCodeEvents类中函数声明为:
HRESULT Fire_CashPolled(LONG lMoney);
HRESULT Fire_ReturnStatus(SHORT sCode, CHAR * pboolCancel);第一个问题是boolean是自动化兼容的类型呀?为什么在代理类中会将IDL里的boolean*改成CHAR*?
第二个问题是我用VB测试的时候,使用WithEvents声明了一个对象,但无法链接ReturnStatus事件,而CashPolled可以正常链接.
代码如下:
Private WithEvents cc As IHWDLib.CashCode
Private Sub cc_CashPolled(ByVal lMoney As Long)
    MsgBox lMoney
End Sub
使用VB的IDE添加Sub cc_ReturnStatus的时候,VB弹出对话框,内容是:
"函数或接口标记为限制的,或函数使用了 Visual Basic 中不支持的自动类型"PS:
Visual C++ 6.0 sp6
Visual Basic 6.0 sp6

解决方案 »

  1.   

    晕.
            [
    object,
    uuid(C8C090A7-361B-4484-BBD7-81479B34F01A),
    dual,
    helpstring("ISerialPort Interface"),
    pointer_default(unique)
    ]
    interface ISerialPort : IDispatch
    {
    [id(1), helpstring("method OpenPort")] HRESULT OpenPort([in]BYTE port,[in]long baud,[out,retval]boolean *pboolResult);
    VB测试的时候,使用后绑定,即使用CreateObject来创建对象的话,OpenPort函数可以正常调用OpenPort函数,如下:
    Dim sp
        Set sp = CreateObject("IHWD.SerialPort")
        sp.OpenPort 2, 9600
        If (sp.IsOpened()) Then
            sp.ClosePort
        Else
            MsgBox "未能成功打开串口"
        End If但是使用前绑定,即现在VB中添加类型库的引用,然后直接用
    Private mSP As New IHWDLib.SerialPort
    来定义一个对象,如下代码报错:
    mSP.OpenPort 2, 9600报的错误跟上一个一样:
    "函数或接口标记为限制的,或函数使用了 Visual Basic 中不支持的自动类型" 看来是不支持boolean*?那么应该使用什么类型呢?boolean是自动化兼容的类型呀!
    难道要使用BOOL吗?BOOL是通过typedef int BOOL定义的,应该不对吧?
      

  2.   

    IDL      VC++           VB 
    boolean  Unsigend char       不支持
    byte     Unsigend char      不支持
    small    char           不支持
    short    short         Integer
    long    long           Long 
    byper   _int64          不支持
    float    float        Single
    double    double        Double
    char    unsigned char      不支持
    wchar_t  wchar_t          Integer
    enum     enum            Enum
    VARIANT   VARIANT           Variant
    BSTR      BSTR         String
    VARIANT_BOOL sHORT{-1/0} Boolean{True/Flase}
      

  3.   

    boolean不是标准的调度接口的数据类型,必须是VARIANT_BOOL,VB中的Boolean对应的也是VARIANT_BOOL.
    VB中的后绑定不进行类型检查,而是尝试执行内部的VARIANT类型转换,从1字节的boolean转换成2字节的VARIANT_BOOL是能够成功的,所以运行结果看起来是成功的,但是前绑定会做类型检查,所以在编译期间就会提示类型错误。
      

  4.   

    在生成代理类的时候.
    如下函数: HRESULT Fire_ReturnStatus(SHORT sCode, VARIANT_BOOL * pboolCancel)
    {
    CComVariant varResult;
    T* pT = static_cast<T*>(this);
    int nConnectionIndex;
    CComVariant* pvars = new CComVariant[2];
    int nConnections = m_vec.GetSize();

    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
    {
    pT->Lock();
    CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
    pT->Unlock();
    IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
    if (pDispatch != NULL)
    {
    VariantClear(&varResult);
    pvars[1] = sCode;
    pvars[0] = pboolCancel;
    DISPPARAMS disp = { pvars, NULL, 2, 0 };
    pDispatch->Invoke(0x2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
    }
    }
    delete[] pvars;
    return varResult.scode;

    }
    编译的时候有一个警告:
    warning C4800: 'short *' : forcing value to bool 'true' or 'false' (performance warning)
    在pvars[0] = pboolCancel;这一行.
    如何处理?
      

  5.   

    改成了:
    pvars[0].vt = VT_BOOL|VT_BYREF;
    pvars[0].pboolVal = pboolCancel;
    DISPPARAMS disp = { pvars, NULL, 2, 0 };
    pDispatch->Invoke(0x2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
    编译过去了但是我从VB添加了如下代码
    Private Function mCC_ReturnStatus(ByVal sCode As Integer) As Boolean
        MsgBox sCode
        mCC_ReturnStatus = True
    End Function
    这个函数不会执行到,确定上面的Invoke是执行了的,我单步跟进去看了的.VB中我还链接了另外一个事件,如下:
    Private Sub mCC_CashPolled(ByVal lMoney As Long)
        MsgBox lMoney
    End Sub
    这个是可以执行到的.
      

  6.   

    可以了,我把IDL文件改了一下:
    [id(2), helpstring("method ReturnStatus")] HRESULT ReturnStatus([in]short sCode,[out,retval]boolean *pboolCancel);把后面的retval属性去掉就可以了,但是不明白为什么不能用retval
      

  7.   

    是自动生成的.
    我在IDL里面写的是VARIANT_BOOL*
    但是生成的代理类里面是:
    pvars[0] = pboolCancel;另外还有一个问题请教:
    CCashCode类实现ICashCode接口,该类还包容了另一个接口ISerialPort,内部变量为ISerialPort *m_pSerialPort;
    在ICashCode的某一个导出函数中,需要另外开一个线程.
    该线程中需要使用包容的ISerialPort接口.我不知道怎么可以在该线程中使用IserialPort接口.
    另外,如果线程函数中需要调用CCashCode的成员函数,是否直接传递this就行?不需要列集吧?
      

  8.   

    除非组件是自由线程模型,否则一定需要列集,传递this是不行的
      

  9.   

    谢谢您的回复!1.不知道为什么自动生成的代理类对于VARIANT_BOOL*型的参数处理不正确,需要手动改?
    2.线程函数中需要使用包容的ISerialPort接口,还需要调用CCashCode类的某些函数(非ICashCode接口函数).这样的话,是需要列集ISerialPort和ICashCode两个接口吗?ICashCode接口需要列集吗?ISerialPort接口需要列集吗?
      

  10.   

    谢谢您的回复! 1.不知道为什么自动生成的代理类对于VARIANT_BOOL*型的参数处理不正确,需要手动改? 
    2.线程函数中需要使用包容的ISerialPort接口,还需要调用CCashCode类的某些函数(非ICashCode接口函数).这样的话,是需要列集ISerialPort和ICashCode两个接口吗?ICashCode接口需要列集吗?ISerialPort接口需要列集吗?
      

  11.   

    问题1:没遇到过,这种类型向导生成应该不会出错。
    问题2:牢记一个原则,如果你使用的接口指针是一个代理接口,就不能使用非接口方法的函数;如果是在组件所在套间线程,可以把接口static_cast成对象指针再调用任何函数(包括非接口方法)
      

  12.   

    我就把它当作一般的DLL,那么开一个工作线程的时候,也是可以传递this指针来调用其成员函数的呀.
    为什么COM的DLL就不行呢?class CCashCode:public ICashCode
    ...
    {
    public:
    //ICashCode
    ICashCode_Func1();protected:
    static ULONG threadProc(LPVOID);
    void Func2();private:
    ISerialPort   *m_pSerialPort;  //包容之,在FinalConstruct中CoCreateInstance的.
    };在CCashCode类的threadProc中,需要调用到Func2,而Func2中需要用到m_pSerialPort,应该怎么处理呢?
      

  13.   

    一般的DLL,在某一个class中开工作线程的时候,可以通过传递this指针来让工作线程调用该对象的成员函数.
    为什么做成COM的DLL就不行呢? 
    class CCashCode:public ICashCode 
    ... 

    public: 
    //ICashCode 
    ICashCode_Func1(); protected: 
    static ULONG threadProc(LPVOID); 
    void Func2(); private: 
    ISerialPort  *m_pSerialPort;  //包容的ISerialPort接口,在FinalConstruct中进行的CoCreateInstance.
    }; 
    在CCashCode类的threadProc中,需要调用到Func2(非ICashCode接口的成员函数,是普通的类辅助函数),而Func2中需要用到m_pSerialPort,应该怎么处理呢?