我在IDL中声明了自己的结构,可是编译的时候硬是说名称没有声明……郁闷!我用的是VC.NET,错误信息如下:
d:\files\com\mp3tool\mp3file.h(32): error MIDL2025 : syntax error : expecting a type specification near "MP3_INFO_IDV1"
IDL代码如下:
// Mp3File.h : CMp3File 的声明#pragma once
#include "resource.h"       // 主符号
#include <string>using namespace std;// Struct of Mp3 File infomation IDv1
typedef struct _MP3_INFO_IDV1
{
char Tag[3]; // IDv1标志,始终为“TAG”
char Title[30]; // 标题
    char Artist[30]; // 艺术家
char Album[30]; // 专辑
char Year[4]; // 年代
char Comment[30]; // 注释
char Genre; // 风格
}MP3_INFO_IDV1;
// IMp3File
[
object,
uuid("2571A8A7-E284-4F88-A42C-A1AF74F8FDEE"),
dual, helpstring("IMp3File 接口"),
pointer_default(unique)
]__interface IMp3File : IDispatch
{
[id(1), helpstring("方法Open")] HRESULT Open([in] LPCTSTR lpszFilename);
[id(2), helpstring("方法Close")] HRESULT Close(void);
[id(3), helpstring("方法GetMp3Info")] HRESULT GetMp3Info([out] MP3_INFO_IDV1* info);
[id(4), helpstring("方法SetMp3Info")] HRESULT SetMp3Info([in] MP3_INFO_IDV1* info);
};// CMp3File[
coclass,
threading("apartment"),
vi_progid("Mp3Tool.Mp3File"),
progid("Mp3Tool.Mp3File.1"),
version(1.0),
uuid("329108FE-25AB-437E-A270-F78613E317DC"),
helpstring("Mp3File Class")
]
class ATL_NO_VTABLE CMp3File : 
public IMp3File
{
public:
CMp3File()
{
}
DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct()
{
return S_OK;
}

void FinalRelease() 
{
}public: STDMETHOD(Open)(LPCTSTR lpszFilename);
STDMETHOD(Close)(void);
STDMETHOD(GetMp3Info)(MP3_INFO_IDV1* info);
STDMETHOD(SetMp3Info)(MP3_INFO_IDV1* info);
protected:
// // IDv1 Information
MP3_INFO_IDV1 m_Info1;
// // Full path name
string m_strFileName;
// // Opened Mp3 File handle
HANDLE m_hFile;
};

解决方案 »

  1.   

    不行的,我发现这东西不是IDL文件,是不是这里出错了啊!
      

  2.   

    你也可以做一个申明结构的头文件,然后在IDL文件里包含进去,你的IDL文件就可以用已经定义的结构了!
      

  3.   

    我是放到一个头文件中声明的自己的数据结构,调用的时候
    #include “mystruct.h”,但是编译不能通过。
    后来改为“mystruct.idl”,编译能通过,但是不知道这样会不会有问题。btw:我用的是VC 6.0
      

  4.   

    这个要看看接口是从哪里继承来的,如果是从IUknown继承过来的,是比较简单的,如果是从DIspatch继承来的,就有一点麻烦了!
      

  5.   

    看看这个。
    简要说明: 
      (1) 从IUnknown继承的自定义接口   把数据结构直接传送给基于VTable接口的方法,只适用于由MIDL编译生成的proxy/stub DLL调度的接口,不能用于Invoke();(参UserDefinedDataType(1))  a.在一个新的.h文件中定义自定义数据结构.  b.在.idl文件最前面加入这个.h文件,比如:#include "MyStruct.h"   c.给从IUnknown派生的接口加入使用了自定义数据结构的方法。  d.在客户程序的stadafx.h最下面加入#import指令,如:    #import "..\test3.tlb" no_namespace   在生成的.tlh文件中,会自动包含了用户自定义数据结构的定义。  e.在客户程序需要的时侯调用组件接口函数。  整个过程非常简单,与使用一般的自定义数据类型无异。  另外也可以很方便的使用自定义数据结构数组,使用方法如下:   HRESULT Test2([in]int nCount, [in, size_is(nCount)]MyStruct *pStruct)   (2)从IDispatch继承的双接口对于从IDispatch继承的双接口就不能象方法一那样直接在接口方法里申请自定义类型了,因为双接口必须要用与自动化兼容的类型。所以采用以下的步骤。  (参UserDefinedDataType(2))  a.首先在.idl文件中加入如下几句,定义一个自定义数据类型。    typedef [ uuid(44ABAE82-A173-11d4-98DB-0080C8F5B2E4)]
        struct MyStruct
        {
            int x;
            int y;
        }MyStruct;   b.接口方法参数定义为VARIANT类型,指针也一样。  c.客户端通过ClassWiard导入类型库(用#import也可以,不过这里要验证自动化)  d.客户程序中要加入MyStruct的定义  e.客户程序中加入以下代码:    const GUID GUID_MyStruct=
    {0x44ABAE82,0xA173,0x11d4,{0x98,0xDB,0x00,0x80,0xC8,0xF5,0xB2,0xE4}};
        const GUID LIBID_TEST6Lib =
    {0x67061661,0xa2cb,0x11d4,{0x98,0xdb,0x00,0x80,0xc8,0xf5,0xb2,0xe4}};    ITypeLib* pTypeLib=NULL;
        ITypeInfo* pTypeInfo=NULL;
        IRecordInfo* pRecordInfo=NULL;    LoadRegTypeLib(LIBID_TEST6Lib, 1, 0, LANG_NEUTRAL, &pTypeLib);
        pTypeLib->GetTypeInfoOfGuid(GUID_MyStruct, &pTypeInfo);
        GetRecordInfoFromTypeInfo(pTypeInfo, &pRecordInfo);    MyStruct *pMyStruct = new MyStruct;
        pMyStruct->x = pMyStruct->y = 100;    VARIANT vr;
        VariantInit(&vr);
        vr.vt = VT_RECORD;        //表明自定义类型
        vr.pvRecord = (PVOID)pMyStruct;  //指向实际数据
        vr.pRecInfo = pRecordInfo;    //包含了数据的一些信息
        test6.Test2(vr);         //调用接口方法    pTypeLib->Release();
        pTypeInfo->Release();
        pRecordInfo->Release();
      f.在服务器组件接口方法的实现中加入以下几句:    if (vr.vt == VT_RECORD)
        {
          IRecordInfo *pRecordInfo = vr.pRecInfo;
          PVOID   pMyStruct   = vr.pvRecord;
          VARIANT  varX, varY;
          int x=0, y=0;      VariantInit(&varX);
          VariantInit(&varY);
          pRecordInfo->GetField(pMyStruct, L"x", &varX);//获得x字段的值
          if (varX.vt == VT_INT)
          {
            x = varX.intVal;
          }
          pRecordInfo->GetField(pMyStruct, L"y", &varY);//获得y字段的值
          if (varX.vt == VT_INT)
          {
            y = varY.intVal;
          }
        }
    补:  a.通过VARIANT,VT_RECORD,IRecordInfo的这种方法可以用自动化来传递自定义类型数据,但实际上这种方法只适用于双接口的情况。其原因在于实现组件IDispatch接口的IDispatchImpl类身上,它是通过VTable来调用方法的。如果是纯Dispatch接口就不能用这种方法,而我经过试验,暂时无法用这种方法实现dispinterface的情况。  b.同样的方法适用于安全数组,如果传递一个自定义数据结构的数组,则要用到SAFEARRAY,注意用类似SafeArrayCreateEx(VT_RECORD,1,&rgbounds,pRecInfo)的方法来创建数组。  (3)用dispinterface说明的纯IDispatch接口暂时没找到方法。
      

  6.   

    好吧,我来告诉你。把声明放进IDL文件里面去,绝对没有问题。当然你也可以#include 进去。
      

  7.   

    __interface IMp3File : IDispatch
    {
    [id(1), helpstring("方法Open")] HRESULT Open([in] LPCTSTR lpszFilename);
    [id(2), helpstring("方法Close")] HRESULT Close(void);
    [id(3), helpstring("方法GetMp3Info")] HRESULT GetMp3Info([out] MP3_INFO_IDV1* info);
    [id(4), helpstring("方法SetMp3Info")] HRESULT SetMp3Info([in] MP3_INFO_IDV1* info);
    };在MP3_INFO_IDV1前面写上struct就可以了