我做了一个Dcom服务器,在服务器端的接口为
[id(3), helpstring("method TestExcute")] HRESULT TestExcute([in]BSTR sql,[out, retval]BSTR *result);STDMETHODIMP CDBServ::TestExcute(BSTR sql, BSTR *result)
{
// TODO: Add your implementation code here
return S_OK;
}
我在客户端调用TestExcute方法,总是发生异常 BSTR bstr;

BSTR sqlBstr = _com_util::ConvertStringToBSTR(LPCTSTR(str));

pIDBserv->TestExcute(sqlBstr,&bstr);

解决方案 »

  1.   

    BSTR bstr=::SysAllocString(L"haha");
    BSTR sqlBstr = _com_util::ConvertStringToBSTR(LPCTSTR(str));
    pIDBserv->TestExcute(sqlBstr,&bstr);“当把字符串作为[in]参数传个一个方法时,调用方有责任在调用之前先调用SysAllocString,然后在方法完成(返回)之后调用SysFreeString。”(摘自COM本质论)
      

  2.   

    关键我想还是没有分配内存吧,BSTR只是相当于一个OLECHAR*(WCHAR*),ConvertStringToBSTR要操作缓冲区里的内存就出错了。BSTR bstr;之后bstr实际上是一个未出世化的指针(0xcccccccc),*0xcccccccc当然会报错了。“‘当把字符串作为[in]参数传个一个方法时,调用方有责任在调用之前先调用SysAllocString,然后在方法完成(返回)之后调用SysFreeString。’(摘自COM本质论)”
    只是一个原则上的编码方式问题,并不是说在组件中分配内存然后客户端释放就不能实现。其实关于COM中的字符串问题更好的教材是《深入解析ATL》,讨论相当详尽。
      

  3.   

    1.
    interface Ihorse : IDispatch
    {
    [id(1), helpstring("method eat")] HRESULT eat([in]BSTR str,[in,out]BSTR* ret);
    };
    //
    STDMETHODIMP Chorse::eat(BSTR str, BSTR *ret)
    {
    CComBSTR strt = str;
    strt.Append(OLESTR("XXX"));
    *ret = strt.Copy(); // TODO: Add your implementation code here return S_OK;
    }
    3.
    void CTestclientDlg::OnButton1() 
    {
    ::CoInitialize( NULL );

    CLSID clsid = CLSID_horse;
    COAUTHINFO cai = {  
    RPC_C_AUTHN_NONE,
    RPC_C_AUTHZ_NONE,
    0,
    RPC_C_AUTHN_LEVEL_NONE,
    RPC_C_IMP_LEVEL_IMPERSONATE,
    0,
    EOAC_NONE
    };
    MULTI_QI mqi = { &IID_Ihorse, 0, 0 };
    COSERVERINFO csi = { 0, OLESTR("127.0.0.1"), &cai, 0 };
    HRESULT hr = CoCreateInstanceEx(clsid, NULL, 
    CLSCTX_REMOTE_SERVER, &csi, 1, &mqi);
    if(FAILED(hr)) 
    {
    AfxMessageBox("生成接口出错,可能没有初使化com!");
    ::CoUninitialize();
    return;
    }
    Ihorse *pGN = (Ihorse *)mqi.pItf;
    CComBSTR str = "sdf";
    CComBSTR str1;
    pGN->eat(str,&str1);
    CString strout = str1.Copy();
    AfxMessageBox(strout);
    ::CoUninitialize();

    }