当传字符串给com exe时用
VARIANT va[3];
VariantInit(&va[0]);
VariantInit(&va[1]);
VariantInit(&va[2]);
va[2].vt = VT_BSTR;
va[2].bstrVal = L"my string";
。。。
的方式传给com exe。
如果我要传一个结构体比如mystruct对象给com exe的话呢?还有如果我要获取多个返回值怎么弄?
你的 COM 接口是如何定义的?
如果传入字符串的话是
STDMETHOD(myfunc)(BSTR param1, BSTR param2, BSTR param3, LONG* lRet);
结构体的话可能应该是结构体指针?
@Jingle Guo: 就该接口:STDMETHOD(myfunc)(BSTR param1, BSTR param2, BSTR param3, LONG* lRet),请你写段调用代码,然后再给一个包含结构体参数的接口定义。
@Launcher:
STDMETHOD(myfunc)(MyStruct* param1, LONG* lRet)
@Jingle Guo: 你这个方法:STDMETHOD(myfunc)(BSTR param1, BSTR param2, BSTR param3, LONG* lRet) ,你的调用代码是怎样的?
@Launcher:
HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, VARIANT* pramArray,int cArgs) {
// Begin variable-argument list //va_list marker; //va_start(marker, cArgs);
if (!pDisp) {
_putws(L"NULL IDispatch passed to AutoWrap()"); //_exit(0);
return E_INVALIDARG;
}
// Variables used DISPPARAMS dp = { NULL, NULL, 0, 0 };
DISPID dispidNamed = DISPID_PROPERTYPUT;
DISPID dispID;
HRESULT hr;
// Get DISPID for name passed // GetUserDefaultLCID()
hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1,LOCALE_USER_DEFAULT , &dispID);
if (FAILED(hr)) {
wprintf(L"IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx\n", ptName, hr); //_exit(0);
return hr;
}
// Allocate memory for arguments
VARIANT *pArgs = new VARIANT[cArgs + 1]; // Extract arguments...
for(int i=0; i < cArgs; i++) {
pArgs[i] = pramArray[i];//va_arg(marker, VARIANT);
}
// Build DISPPARAMS dp.cArgs = cArgs; dp.rgvarg = pArgs;
// Handle special-case for property-puts
if (autoType & DISPATCH_PROPERTYPUT) {
dp.cNamedArgs = 1;
dp.rgdispidNamedArgs = &dispidNamed;
}
// Make the call
hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType, &dp, pvResult, NULL, NULL);
if (FAILED(hr)) {
wprintf(L"IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx\n", ptName, dispID, hr); //_exit(0);
return hr;
}
delete[] pArgs;
return hr;
}
VARIANT va[3];
VariantInit(&va[0]);
VariantInit(&va[1]);
VariantInit(&va[2]);
va[2].vt = VT_BSTR;
va[2].bstrVal = L"my string";
va[1].vt = VT_BSTR;
va[1].bstrVal = L"my string";
va[0].vt = VT_BSTR;
va[0].bstrVal = L"my string";
AutoWrap(DISPATCH_METHOD, &result, pConvert, L"myfunc",va, 3);
nRet = result.intVal;
VariantClear(&va[0]);
VariantClear(&va[1]);
VariantClear(&va[2]);
VariantClear(&x);
VariantClear(&result);
@Jingle Guo: 哦,原来你是这样调用的,那么对于方法 STDMETHOD(myfunc)(MyStruct* param1, LONG* lRet) 中的结构体指针参数来说,可以这样使用 VARIANT:
VARIANT vt;
vt.byref = CoTaskMemAlloc(sizeof(MyStruct));
@Launcher: 喔,我回头试试,谢谢!
@Launcher: 我原来设想的是STDMETHOD(myfunc)(MyStruct* param1, LONG* lRet)
但是我在idl文件中进行定义的时候因为里面含有wstring,加上string的头文件后会提示“eh.h is only for c++”,是不是MyStruct结构体里不能包含一些<string>这种定义啊?
我试着用PVOID代替MyStruct*也不被允许。
用VARIANT* 代替MyStruct*倒是允许,但是我用下面的方式将参数传过去的时候调用失败
va[0].vt = VT_VARIANT;
va[0].pvarVal = (VARIANT*)(&mystruct)
应该用什么方式解决这个问题啊?
@Jingle Guo: 这涉及到 COM 中对象的封送问题,你可以去了解下。
VARIANT vt;
vt.byref = CoTaskMemAlloc(sizeof(MyStruct));
struct MySturct{ WCHAR wszStr[200];}
@Launcher: 我用了个最简单的例子试了一下还是不行,下面的方式帮我看一下有啥问题吗?
typedef struct
{
int x;
int y;
} Position;
被调用的exe com里面:
STDMETHODIMP CFileConvert::ConvertFile(Position* v, LONG* lRet)
{
OutputDebugString(L"ConvertFile");
*lRet = 0;
return S_OK;
}
调用的时候这样弄:
VARIANT va[1];
VariantInit(&va[0]);
va[0].vt = VT_BYREF;
Position* pos = (Position*)::CoTaskMemAlloc(sizeof(Position));
pos->x = 100;
pos->y = 200;
va[0].byref = pos;
AutoWrap(DISPATCH_METHOD, &result, pConvert, L"ConvertFile",va, 1);
就是调不起来,请问是哪里的问题啊?
@Jingle Guo:
typedef
[
uuid(xxxxx-xxxxx-xxxx--xxxxx),
helpstring("Position Struct")
]
struct Position
{
int x;
int y;
} Position;
@Launcher:
试了,还是不行,难道只能把结构拆开了?
typedef
[
uuid(1CED1C51-189B-4A98-98AD-1F8137563571),
helpstring("Position Struct")
]
struct Position
{
int x;
int y;
} Position;
@Jingle Guo: 把 struct Position 修改为 struct IPosition,然后作为接口使用。或者把 Position 作为 SAFEARRAY 传递。或者 STDMETHODIMP CFileConvert::ConvertFile(VARIANT * v, LONG* lRet)
@Launcher:
方案1:不知道怎么作为接口使用
方案2和3貌似差不多,都是要把结构体倒腾过去再倒腾回来的样子,算了我还是老老实实的把结构体拆开来传吧。
谢谢您的帮助,感觉耽误了您不少时间的样子。。。
@Jingle Guo: 有空编写个使用 ADO 更新数据库的代码,你就能理解了。