1)如何在IDL文件中声明自定义类型(eg. struct): 这是我的IDL文件,可以通过测试--可以在VB中调用,但……
import "oaidl.idl";
import "ocidl.idl"; typedef 
// [
// uuid(EF726672-F275-45cd-99FB-8932B0DF1AB4)
// ]
struct tagColor {
short red;
short green;
short blue;
} Color;
[
object,
uuid(5F4F5902-8592-41C4-99E1-DC729ED8755D),
dual,
helpstring("ISCX_ATL Interface"),
pointer_default(unique)
]
interface ISCX_ATL : IDispatch
{
[id(1), helpstring("method Add")] HRESULT Add([in]int addNum, [in]int addNumOther, [out]int *result);
[id(2), helpstring("method Subtract")] HRESULT Subtract([in]int num, [in]int numOther, [out]int *result);
[id(3), helpstring("method SetColor")] HRESULT SetColor([in]const Color *pClr);
[id(4), helpstring("method GetColor")] HRESULT GetColor([out, retval] Color *pColor);
};[
uuid(648E314A-C6EB-47CE-866E-E57A30DFDE67),
version(1.0),
helpstring("ComDemo 1.0 Type Library")
]library COMDEMOLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb"); [
uuid(4230782D-B78A-4957-BC29-855BA923A61A),
helpstring("SCX_ATL Class")
]
coclass SCX_ATL
{
[default] interface ISCX_ATL;
}; struct Color;
};
编译有WARING:
A)warning MIDL2039 : interface does not conform to [oleautomation] attribute : [ Parameter 'pClr' of Procedure 'SetColor' ( 
Interface 'ISCX_ATL' ) ]
B)warning MIDL2039 : interface does not conform to [oleautomation] attribute : [ Parameter 'pColor' of Procedure 'GetColor' 
( Interface 'ISCX_ATL' ) ]
为什么?????2)如果将[id(4), helpstring("method GetColor")] HRESULT GetColor([out, retval] Color *pColor);中参数写成[out, retval] Color **pColor,那在VB中如何调用??

解决方案 »

  1.   

    1)
    MIDL2039 : interface does not conform to [oleautomation] attribute 
    The interface does not meet the requirements for and Automation interface. Check to make sure the interface is derived from IUnknown or IDispatch. 
    2)
    我认为没法调用。
      

  2.   

    1)我都是通过用菜单来创建ATL object和add function,所以应该是继承IDispatch.2)我看有些程序,返回值是指向指针的指针,即2级指针(如接口的2级指针)。如果这样的话,用VB就不能调用COM了?
      

  3.   

    1、提示的意思,应该是让你添加上[oleautomation] attribute 
    oleautomation
    [ oleautomation, uuid(string-uuid)[ , interface-attribute-list] ] 
         interface interface-name : base-interface string-uuid 
    Specifies a UUID string generated by the uuidgen utility. 
    interface-attribute-list 
    Specifies other attributes that apply to the interface as a whole. 
    interface-name 
    Specifies the name of the interface. 
    base-interface 
    Specifies the name of an OLE Automation interface from which this derived interface inherits member functions, status codes, and interface attributes. All OLE Automation interfaces are derived from IUnknown or IDispatch. 
    Example
    library Hello
    {
     importlib("stdole32.tlb");
        [
          uuid( . . .),
          helpstring("Application object for the Hello application."),
          oleautomation,
          dual
        ]
        interface IHello : IDispatch
        {. . .} 
     
      

  4.   

    Dispatch  接口 不支持自定义的结构
      

  5.   

    加了[oleautomation] attribute,警告还是一样。
      

  6.   

    传递自定义类型必须通过VARIANT为中介,按以下三步做:
    1 定义自定义类型的struct;
    2 分配GUID;
    3 将函数中的参数定义为VARIANT(本题中的SetColor应该声明为:
      SetColor([in]const VARIANT pClr);
      GetColor([out, retval] VARIANT *pColor);4 在函数中指派IRecordInfo指针,为VARIANT参数打包(导出)或解包(导入)
    GetColor(VARIANT *pColor)
    {
      ITypeInfo *pTypeInfo;
      IRecordInfo *pRecInfo;
      LoadRegTypeLib(LIBID_COMDEMOLib,1,0GetUserDefaultLCID,&pTypeInfo);
      pTypeInfo->GetTypeInfoOfGuid(REFIID_ISCX_ATL,&pRecInfo);  pColor->vt=VT_RECORD;
      pColor->pRecInfo=pRecInfo;pRecInfo->Addref();
      pRecInfo->RecordCreateCopy(&m_oColor,&(pColor->pvRecord));  return S_OK;
    }(随手写的代码,没上有机调试,但大致是这样,没写错误处理)Set就不写了,一回事——但愿你不会骂我——干嘛写这么多?看来我还是解释一下:BASIC是不可能直接认识你向它传递的Color结构的,即使你给Color指定了GUID.为什么呢?因为BASIC是通过ITypeInfo接口来读类型库*.tlb,然后用pRecordInfo接口来读这个*.tlb中的有GUID标记的任何数据结构,包括枚举、接口、自定义结构。现在你直接把一个Color给了BASIC编译器,它怎么办呢?BASIC说:“我的确得到了你给的数据块,但我不知道它是什么?一堆数据放在一起,我分不开啊?盖茨没教我解密!”:)于是你得告诉它,你给的数据是怎么构成的,但这怎么做呢?负责这件事的就是IRecordInfo 指针,这个指针可以描述自定义类型的结构——这必须由你提供给它!于是你就得传两个数据给BASIC,一是你的自定义类型的实例,另一个是IRecordInfo接口指针。现在的问题就简单了,但你马上会发现传一个数据就得用两个变量的办法好笨,于是你想到了VARIANT,它不是号称可以包容一切数据吗?的确,COM也想到了这一点,COM在自定义类型的数据上有了一个约定:用VARIANT传递自定义类型实例时,必须给VARIANT中的三个成员赋值:
    VARIANT.vt = VT_RECORD   (必须等于VT_RECORD,表示自定义类型)
    VARIANT.pvRecord=实例的数据块地址
    VARIANT.pRecInfo = 自定义类型的IRecordInfo接口指针然后,通过VARIANT来传。BASIC认识VARIANT,所以能够间接地识别你的类型。
    也就是说当BASIC调用GetColor(VARIANT *pColor)时,它会先检查pColor中的vt成员,发现是VT_RECORD后,它再检查pRecInfo,通过它读类型信息,最后从pvRecord中读数据,读完后还会自动清除它(就象清除BSTR一样)。现在你再读上面的代码,大概不会骂我用那么多费码了。如果你认为这样做太麻烦,也行,有一个类,把这些步骤全省了,你可以参见:
    http://blog.csdn.net/IUnknown886/archive/2005/04/12/343714.aspx