为了在atl(EXE SERVER类型)和客户端之前传递自定义数据
struct node{
    BSTR description;    /* optional element of type xsd:string */
    BSTR id;    /* optional element of type xsd:string */
    BSTR name;    /* optional element of type xsd:string */
    struct {BSTR* tags;int numberOfTags;}
}
,我在MDIL中定义了自定义的数据结构.
typedef struct TAGS_DEF {
    BSTR* item;  //pointer to the memory where tags are stared.
    int length;  //number of tags
}TAGS;
typedef struct RESNODE {
    BSTR description;    /* optional element of type xsd:string */
    BSTR id;    /* optional element of type xsd:string */
    BSTR name;    /* optional element of type xsd:string */
    TAGS tags;
}ResNode;
和响应添加的接口.
    [id(6), helpstring("方法AddOrModifyRes")] HRESULT AddOrModifyRes([in] ResNode* res, [in] BSTR operat);
   但是在exe server模式的ATL项目中,这个接口不能正确的被执行.就是说如果在客户端执行.
        hr = spf.CoCreateInstance( CLSID_DataServer);
        if( FAILED( hr ))    throw( _T("服务器注删失败!"));
        ResNode rn;
        BSTR* tmpStr=NULL;
        rn.tags.item=tmpStr;
        rn.tags.length=0;
        BSTR tmp=L"add";
        spf->AddOrModifyRes(rn,tmp);
这样的语句的时候,AddOrModifyRes这个函数并未被正确的执行.很奇怪的是在ATL项目被定制成DLL的类型的时候,就不存在上述问题.我的MIDL的定义是
// monwebDataService.idl : monwebDataService 的 IDL 源
//// 此文件将由 MIDL 工具处理以
// 产生类型库(monwebDataService.tlb)和封送处理代码。import "oaidl.idl";
import "ocidl.idl";
typedef struct TAGS_DEF {
    BSTR* item;  //pointer to the memory where tags are stared.
    int length;  //number of tags
}TAGS;
typedef struct RESNODE {
    BSTR description;    /* optional element of type xsd:string */
    BSTR id;    /* optional element of type xsd:string */
    BSTR name;    /* optional element of type xsd:string */
    TAGS tags;
}ResNode;
[
    object,
    uuid(EEC2233E-D1A7-435A-9CBD-48901778AEB7),
    dual,
    nonextensible,
    helpstring("IDataServer 接口"),
    pointer_default(unique)
]
interface IDataServer : IDispatch{
    [id(1), helpstring("方法IsDataOK")] HRESULT IsDataOK([in,out] BYTE* sucFlag);
    [id(2), helpstring("方法AddOrModifyRes")] HRESULT AddOrModifyRes([in] ResNode* res, [in] BSTR operat);
};
[
    uuid(B79310B8-7A31-4598-897B-A9DD16EA3C33),
    version(1.0),
    helpstring("monwebDataService 1.0 类型库")
]
library monwebDataServiceLib
{
    importlib("stdole2.tlb");
    [
        uuid(8256EA22-CA60-4914-B8EB-F215E01C91A7),
        helpstring("DataServer Class")
    ]
    coclass DataServer
    {
        [default] interface IDataServer;
    };
};

解决方案 »

  1.   

    1,对于跨进程的组件调用,如果一定要用指针作为参数,那么所有指针指向的Buffer的大小不得不在设计期间就能确定,不确定是不可以用在这种COM接口上的。如果能确定,则应该在IDL里用size_is()来修饰一下指针。例如:有指针P指向一个128字节的Buffer,则在接口上应该这样写,HRESULT Func([in, size_is(128)] const BYTE* p);或HRESULT Func([out, size_is(128)] BYTE* p);这是因为进程之间不能相互访问对方的内存,这你应当是一生下来就知道的事情。
      

  2.   

    1,对于跨进程的组件调用,如果一定要用指针作为参数,那么所有指针指向的Buffer的大小不得不在设计期间就能确定,不确定是不可以用在这种COM接口上的。如果能确定,则应该在IDL里用size_is()来修饰一下指针。例如:有指针P指向一个128字节的Buffer,则在接口上应该这样写,HRESULT Func([in, size_is(128)] const BYTE* p);或HRESULT Func([out, size_is(128)] BYTE* p);这是因为进程之间不能相互访问对方的内存,这你应当是一生下来就知道的事情。(接我上一条回复)进程之间不能相互访问对方的内存,而你的程序之所以在size_is的帮助下,能够访问接口另一侧的指针,是因为size_is告诉COM指针指向Buffer的大小,然后COM暗地里创建了一个size_is大小的Buffer,然后把接口另一侧真正的Buffer复制到临时创建的Buffer中,并把指针提供了接口这一侧,不信你跟踪一下,这时接口两侧的指针的地址值是不同的。