Wingsun,AKing,猛禽等COM方面的高手请进:为什么COM接口函数中的返回变量的指针为BSTR*可以,但是LPSTR*却不能正确返回COM服务器的值??

书生 2003-02-25 05:24:42
为什么COM接口函数中的返回变量的指针为BSTR*可以,但是LPSTR*却不能正确返回COM服务器的值??

谢谢各位。
帮忙顶也有分。
-书生
...全文
153 82 打赏 收藏 转发到动态 举报
写回复
用AI写文章
82 条回复
切换为时间正序
请发表友善的回复…
发表回复
书生 2003-04-04
  • 打赏
  • 举报
回复
提交了FAQ。
书生 2003-03-05
  • 打赏
  • 举报
回复
哈哈~~
kingcaiyao 2003-03-04
  • 打赏
  • 举报
回复
呵呵,真是聪明一世,糊涂一世,连return S_OK都忘了写,long*可以作为输出函数,是自已精心少写了一行,加上这一行,下面的代码可以通过:
STDMETHODIMP __fastcall TKingcaiyaoImpl::GetData(unsigned short *aa)
{
try
{
*aa=100;
}
catch(Exception &E)
{
return Error(E.Message.c_str(),IID_IKingcaiyao);
}
return S_OK;
}
STDMETHODIMP __fastcall TKingcaiyaoImpl::GetDataA(LPSTR* aa)
{
try
{
*aa="dkdkdkd";
}
catch(Exception &E)
{
return Error(E.Message.c_str(),IID_IKingcaiyao);
}
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
unsigned short aa=0;
IKingcaiyao *pKingcaiyao;
HRESULT hr=::CoCreateInstance(CLSID_Kingcaiyao,0,CLSCTX_LOCAL_SERVER,
IID_IKingcaiyao,(LPVOID*)&pKingcaiyao);
if(hr==S_OK)
{
pKingcaiyao->GetDataA(&aa);
ShowMessage(aa);
pKingcaiyao->Release();
}
//而如果调用GETDATAA这个方法,则会出AV错误
}


Wingsun 2003-03-04
  • 打赏
  • 举报
回复
嗬嗬!经过我的测试没有问题。你们的问题是没有下面这句话:
return S_OK;
//Server
STDMETHODIMP TMyTestInterfaceImpl::Method1(long* Value)
{
*Value = 100;
return S_OK;
}

//Client

void __fastcall TForm1::Button1Click(TObject *Sender)
{
TCOMIMyTestInterface p=CoMyTestInterface::Create();
long w;
p->Method1(&w);
Edit1->Text=IntToStr(w);
}
kingcaiyao 2003-03-03
  • 打赏
  • 举报
回复
To whyandanswer:
我这边调用的得到的结果都是0,我正在找原因。
WhyAndAnswer 2003-03-03
  • 打赏
  • 举报
回复
to kingcaiyao(AKing)
你的代码有点看不懂
Server:
STDMETHODIMP __fastcall TKingcaiyaoImpl::GetData(unsigned short *aa)
{
try
{
*aa=100;
}
catch(Exception &E)
{
return Error(E.Message.c_str(),IID_IKingcaiyao);
}
}
STDMETHODIMP __fastcall TKingcaiyaoImpl::GetDataA(LPSTR* aa)
{
try
{
*aa="dkdkdkd";
}
catch(Exception &E)
{
return Error(E.Message.c_str(),IID_IKingcaiyao);
}
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
unsigned short aa=0;
IKingcaiyao *pKingcaiyao;
HRESULT hr=::CoCreateInstance(CLSID_Kingcaiyao,0,CLSCTX_LOCAL_SERVER,
IID_IKingcaiyao,(LPVOID*)&pKingcaiyao);
if(hr==S_OK)
{
pKingcaiyao->GetDataA(&aa);
//这里得到的值仍为0,而100
////////////////////////////////////////////////////////////
//这里是否是pKingcaiyao->GetData(&aa); 类型不对啊
//我第一次做的时候也是0,但后来不知怎么搞的,怎么做都是100
//////////////////////////////////////////////////////////


ShowMessage(aa);
pKingcaiyao->Release();
}
//而如果调用GETDATAA这个方法,则会出AV错误
}
书生 2003-03-03
  • 打赏
  • 举报
回复
倒,是不支持LPSTR*做输出参数。哈哈~才看见。
书生 2003-03-03
  • 打赏
  • 举报
回复
哈哈,来了好多星星的说。

多谢大家的热烈讨论。
看来结论是:MIDAS中因为使用了IDisPatch接口,只能使用VARIANT类型数据进行交互,而VARIANT又不支持BSTR*。

再次感谢大家的讨论,这个帖子我觉得过段时间再结吧,让更多和我有一样困惑的人能看到。

请各位继续讨论。阅读中。。。
  • 打赏
  • 举报
回复
嗬嗬,人生何处不相逢啊?
勉励前行 2003-03-02
  • 打赏
  • 举报
回复
少COPY了一句:
* May be Automation compatible with some applications.
就是No後面有*號的表示,在某些程序上是可能是可以用的,Borland多麼含糊其詞啊,這麼說,誰敢用啊。
勉励前行 2003-03-02
  • 打赏
  • 举报
回复
IDL type Variant type Automation compatible Description

short VT_I2 Yes 2-byte signed integer
long VT_I4 Yes 4-byte signed integer
single VT_R4 Yes 4-byte real
double VT_R8 Yes 8-byte real
CURRENCY VT_CY Yes currency
DATE VT_DATE Yes date
BSTR VT_BSTR Yes binary string
IDispatch VT_DISPATCH Yes pointer to IDispatch interface
SCODE VT_ERROR Yes OLE Error Code
VARIANT_BOOL VT_BOOL Yes True = –1, False = 0
VARIANT VT_VARIANT Yes pointer to OLE Variant
IUnknown VT_UNKNOWN Yes pointer to IUnknown interface
DECIMAL VT_DECIMAL Yes 16-byte fixed point
byte VT_I1 No* 1-byte signed integer
unsigned char VT_UI1 Yes 1-byte unsigned integer
unsigned short VT_UI2 No* 2-byte unsigned integer
unsigned long VT_UI4 No* 4-byte unsigned integer
__int64 VT_I8 No 8-byte signed real
uint64 VT_UI8 No 8-byte unsigned real
int VT_INT No* system-dependent integer (Win32=Integer)
unsigned int VT_UINT No* system-dependent unsigned integer
void VT_VOID Yes C style VOID
HRESULT VT_HRESULT No 32-bit error code
SAFEARRAY VT_SAFEARRAY Yes OLE Safe Array
LPSTR VT_LPSTR No null terminated string
LPWSTR VT_LPWSTR No wide null terminated string

上面是Automation對各類型的支持列表,可以看BCB幫助的啊,幫助中有,我是COPY過來的。
看到Automation compatible No: LPSTR , LPWSTR
而BSTR卻是可以的。寫COM時請使用Automation compatible的類型。

kingcaiyao 2003-03-02
  • 打赏
  • 举报
回复
cker兄,好久不见了,久违了。。。
RomanticProgrammer:
你有时间试试zgce(牧童)的代码,我觉得CoCreateInstance的实现过程可能和用Dispatch接口的实现机制可能有些不同(我还没有试试),我回去看看书。
对了,你的mail多少?
halibut 2003-03-02
  • 打赏
  • 举报
回复
我来顶!
RomanticProgrammer 2003-03-02
  • 打赏
  • 举报
回复
IDispath是专门为不支持Vatble的语言(入VB,Script..)设计的,所以和Vatble有些不同.
RomanticProgrammer 2003-03-02
  • 打赏
  • 举报
回复
to 牧童:

你使用的是Vtable的方法访问COM接口.而在MIDAS中如果使用IDispatch调接口,则必须使用Automation支持的类型.Automation的基本数据类型是VARIANT结构.

///////////////////////////////////////////

typedef struct tagVARIANT {
VARTYPE vt;
unsigned short wReserved1;
unsigned short wReserved2;
unsigned short wReserved3;
union {
unsigned char bVal; // VT_UI1.
short iVal; // VT_I2 .
long lVal; // VT_I4 .
float fltVal; // VT_R4 .
double dblVal; // VT_R8 .
VARIANT_BOOL boolVal; // VT_BOOL.
SCODE scode; // VT_ERROR.
CY cyVal; // VT_CY .
DATE date; // VT_DATE.
BSTR bstrVal; // VT_BSTR.
IUnknown FAR* punkVal; // VT_UNKNOWN.
IDispatch FAR* pdispVal; // VT_DISPATCH.
SAFEARRAY FAR* parray; // VT_ARRAY|*.
unsigned char FAR* pbVal; // VT_BYREF|VT_UI1.
short FAR* piVal; // VT_BYREF|VT_I2.
long FAR* plVal; // VT_BYREF|VT_I4.
float FAR* pfltVal; // VT_BYREF|VT_R4.
double FAR* pdblVal; // VT_BYREF|VT_R8.
VARIANT_BOOL FAR* pboolVal; // VT_BYREF|VT_BOOL.
SCODE FAR* pscode; // VT_BYREF|VT_ERROR.
CY FAR* pcyVal; // VT_BYREF|VT_CY.
DATE FAR* pdate; // VT_BYREF|VT_DATE.
BSTR FAR* pbstrVal; // VT_BYREF|VT_BSTR.
IUnknown FAR* FAR* ppunkVal; // VT_BYREF|VT_UNKNOWN.
IDispatch FAR* FAR* ppdispVal; // VT_BYREF|VT_DISPATCH.
SAFEARRAY FAR* FAR* pparray; // VT_ARRAY|*.
VARIANT FAR* pvarVal; // VT_BYREF|VT_VARIANT.
void FAR* byref; // Generic ByRef.
};
};



///////////////////////////////////////
牧童027 2003-03-02
  • 打赏
  • 举报
回复
Sorry,我没看清楚就发标了,原来大家在讨论的是IDispatch结口呀!我还以为是直接访问的呢。的确IDispatch是不能对LPSTR*做处理的,因为在VARIANT结构里没有定义。呵呵,不好意思。
daniel_tao 2003-03-02
  • 打赏
  • 举报
回复
宝兰还有问题,大家看看
http://expert.csdn.net/Expert/topic/1482/1482969.xml?temp=.2684748
好像在自动生成.pas的头文件时有问题,也是COM 的
kingcaiyao 2003-03-02
  • 打赏
  • 举报
回复
To zgce:

事实上,用CoCreateInstance这个API函数,你的程序也行不通,我今天试过:
Server:
STDMETHODIMP __fastcall TKingcaiyaoImpl::GetData(unsigned short *aa)
{
try
{
*aa=100;
}
catch(Exception &E)
{
return Error(E.Message.c_str(),IID_IKingcaiyao);
}
}
STDMETHODIMP __fastcall TKingcaiyaoImpl::GetDataA(LPSTR* aa)
{
try
{
*aa="dkdkdkd";
}
catch(Exception &E)
{
return Error(E.Message.c_str(),IID_IKingcaiyao);
}
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
unsigned short aa=0;
IKingcaiyao *pKingcaiyao;
HRESULT hr=::CoCreateInstance(CLSID_Kingcaiyao,0,CLSCTX_LOCAL_SERVER,
IID_IKingcaiyao,(LPVOID*)&pKingcaiyao);
if(hr==S_OK)
{
pKingcaiyao->GetDataA(&aa);
//这里得到的值仍为0,而100
ShowMessage(aa);
pKingcaiyao->Release();
}
//而如果调用GETDATAA这个方法,则会出AV错误
}
事实上你的方法正好是不用双接口,而直接使用标准的COM对象调用方法来实现,而CoYourInterface正好是
为了避免直接调用CoCreateInstance来创建COM对象的实例而设计,它表露了两个静态的方法:Create,CreateRemote
,以便在客户端创建对象的实例.
pp616 2003-03-02
  • 打赏
  • 举报
回复
有点累了。7点过了。该去睡觉了。
lixinwyh 2003-03-02
  • 打赏
  • 举报
回复
我也借这里问个问题,在跨进程使用com的时候,在对待[out]的参数上,必须在客户端创建变量,然后将指针传入com服务端,最后系统自动释放,如果在com服务端创建则客户端不能释放传回的指针,否则报错,但是不释放,会有内存泄漏,能解释一下原因吗?
加载更多回复(62)

1,316

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧