SAFEARRAY(BSTR) 作为 DCOM 中的 [out] 参数无法 return 字符串
SAFEARRAY(BSTR) as [out] parameter in DCOM fails to return strings
我想写一个 DCOM 服务器和一个客户端,以便它们可以交换一些数据。双方都使用 MS Visual Studio 2008 编译,客户端使用纯 WinAPI 连接,proxy/stub 是一个单独的 dll(以防万一)。问题是,我不能 return 一个字符串数组(它已正确填充但客户端收到一个空字符串数组)。
服务器: COM接口的IDL声明有这样的方法:
[id(7)] HRESULT foo([in] int arg1, [out] SAFEARRAY(int)* arg2, [out] SAFEARRAY(BSTR)* arg3);
实施,header 由 Studio 生成:
HRESULT STDMETHODCALLTYPE CoClass::foo(int arg1, SAFEARRAY** arg2, SAFEARRAY** arg3){
SAFEARRAYBOUND bounds;
bounds.cElements = arg1;
bounds.lBound = 0;
*arg2 = SafeArrayCreate(VT_INT, 1, &bounds);
*arg3 = SafeArrayCreate(VT_BSTR, 1, &bounds);
for(LONG i=0; i<arg1; ++i){
int int_value = 42;
BSTR string_value = SysAllocString(L"Hello");
//string_value is correct here
SafeArrayPutElement(*arg2, &i, &int_value);
SafeArrayPutElement(*arg3, &i, &string_value);
//string_value isn't destroyed here (explicitly, at least)
}
return ERROR_SUCCESS;
}
客户:包括Studio-generatedheader:
virtual /* [id] */ HRESULT STDMETHODCALLTYPE foo(
/* [in] */ int arg1,
/* [out] */ SAFEARRAY * *arg2,
/* [out] */ SAFEARRAY * *arg3) = 0;
调用者代码(pInterface
正确初始化,其他调用成功):
SAFEARRAY *pInts = NULL, *pStrings = NULL;
HRESULT error = pInterface->foo(23, &pInts, &pStrings);
// in debugger:
// error is ERROR_SUCCESS, pInts filled properly,
// pStrings is an array of 23 NULLs
其他详情:
- IDL 文件中没有 ID 为 7 的其他方法;
- 使用
[out] BSTR *str
有效,字符串 return 正确编辑;
pInterface
从 CoCreateInstanceEx
呼叫收到;
- 系统上没有旧版本的服务器;
- 代码在 Windows XP 上 运行 没有一些更新,所以使用 Visual Studio 2008 是一个很难绕过的限制。
有人知道我做错了什么吗?
答案由Hans Passant在评论区提供。
答案是:向SAFEARRAY
添加元素的语法对于int
和BSTR
是不同的:
// SAFEARRAY **intArray, **stringArray; LONG i;
int int_value = 42;
BSTR string_value = SysAllocString(L"Hello");
SafeArrayPutElement(*intArray, &i, &int_value);
//SafeArrayPutElement(*stringArray, &i, &string_value); //WRONG!
SafeArrayPutElement(*stringArray, &i, string_value); //Right
请注意阅读语法相同:
// SAFEARRAY *intArray, *stringArray; LONG i;
int int_value;
BSTR string_value;
SafeArrayGetElement(intArray, &i, &int_value);
SafeArrayGetElement(stringArray, &i, &string_value);
我想写一个 DCOM 服务器和一个客户端,以便它们可以交换一些数据。双方都使用 MS Visual Studio 2008 编译,客户端使用纯 WinAPI 连接,proxy/stub 是一个单独的 dll(以防万一)。问题是,我不能 return 一个字符串数组(它已正确填充但客户端收到一个空字符串数组)。
服务器: COM接口的IDL声明有这样的方法:
[id(7)] HRESULT foo([in] int arg1, [out] SAFEARRAY(int)* arg2, [out] SAFEARRAY(BSTR)* arg3);
实施,header 由 Studio 生成:
HRESULT STDMETHODCALLTYPE CoClass::foo(int arg1, SAFEARRAY** arg2, SAFEARRAY** arg3){
SAFEARRAYBOUND bounds;
bounds.cElements = arg1;
bounds.lBound = 0;
*arg2 = SafeArrayCreate(VT_INT, 1, &bounds);
*arg3 = SafeArrayCreate(VT_BSTR, 1, &bounds);
for(LONG i=0; i<arg1; ++i){
int int_value = 42;
BSTR string_value = SysAllocString(L"Hello");
//string_value is correct here
SafeArrayPutElement(*arg2, &i, &int_value);
SafeArrayPutElement(*arg3, &i, &string_value);
//string_value isn't destroyed here (explicitly, at least)
}
return ERROR_SUCCESS;
}
客户:包括Studio-generatedheader:
virtual /* [id] */ HRESULT STDMETHODCALLTYPE foo(
/* [in] */ int arg1,
/* [out] */ SAFEARRAY * *arg2,
/* [out] */ SAFEARRAY * *arg3) = 0;
调用者代码(pInterface
正确初始化,其他调用成功):
SAFEARRAY *pInts = NULL, *pStrings = NULL;
HRESULT error = pInterface->foo(23, &pInts, &pStrings);
// in debugger:
// error is ERROR_SUCCESS, pInts filled properly,
// pStrings is an array of 23 NULLs
其他详情:
- IDL 文件中没有 ID 为 7 的其他方法;
- 使用
[out] BSTR *str
有效,字符串 return 正确编辑; pInterface
从CoCreateInstanceEx
呼叫收到;- 系统上没有旧版本的服务器;
- 代码在 Windows XP 上 运行 没有一些更新,所以使用 Visual Studio 2008 是一个很难绕过的限制。
有人知道我做错了什么吗?
答案由Hans Passant在评论区提供。
答案是:向SAFEARRAY
添加元素的语法对于int
和BSTR
是不同的:
// SAFEARRAY **intArray, **stringArray; LONG i;
int int_value = 42;
BSTR string_value = SysAllocString(L"Hello");
SafeArrayPutElement(*intArray, &i, &int_value);
//SafeArrayPutElement(*stringArray, &i, &string_value); //WRONG!
SafeArrayPutElement(*stringArray, &i, string_value); //Right
请注意阅读语法相同:
// SAFEARRAY *intArray, *stringArray; LONG i;
int int_value;
BSTR string_value;
SafeArrayGetElement(intArray, &i, &int_value);
SafeArrayGetElement(stringArray, &i, &string_value);