首页 新闻 会员 周边 捐助

结构体对象能作为参数传给com exe方法吗?

0
悬赏园豆:30 [已解决问题] 解决于 2014-07-11 16:28

当传字符串给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的话呢?还有如果我要获取多个返回值怎么弄?

Jingle Guo的主页 Jingle Guo | 初学一级 | 园豆:134
提问于:2014-07-08 15:40
< >
分享
最佳答案
0

你的 COM 接口是如何定义的?

收获园豆:30
Launcher | 高人七级 |园豆:45050 | 2014-07-08 15:44

如果传入字符串的话是

STDMETHOD(myfunc)(BSTR param1, BSTR param2, BSTR param3, LONG* lRet);

结构体的话可能应该是结构体指针?

Jingle Guo | 园豆:134 (初学一级) | 2014-07-08 15:53

@Jingle Guo: 就该接口:STDMETHOD(myfunc)(BSTR param1, BSTR param2, BSTR param3, LONG* lRet),请你写段调用代码,然后再给一个包含结构体参数的接口定义。

Launcher | 园豆:45050 (高人七级) | 2014-07-08 15:58

@Launcher: 

STDMETHOD(myfunc)(MyStruct* param1, LONG* lRet)

Jingle Guo | 园豆:134 (初学一级) | 2014-07-08 16:23

@Jingle Guo: 你这个方法:STDMETHOD(myfunc)(BSTR param1, BSTR param2, BSTR param3, LONG* lRet) ,你的调用代码是怎样的?

Launcher | 园豆:45050 (高人七级) | 2014-07-08 16:25

@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 | 园豆:134 (初学一级) | 2014-07-08 16:29

@Jingle Guo: 哦,原来你是这样调用的,那么对于方法 STDMETHOD(myfunc)(MyStruct* param1, LONG* lRet) 中的结构体指针参数来说,可以这样使用 VARIANT:

VARIANT vt;

vt.byref = CoTaskMemAlloc(sizeof(MyStruct));

Launcher | 园豆:45050 (高人七级) | 2014-07-08 16:49

@Launcher: 喔,我回头试试,谢谢!

Jingle Guo | 园豆:134 (初学一级) | 2014-07-08 16:51

@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 | 园豆:134 (初学一级) | 2014-07-11 11:10

@Jingle Guo: 这涉及到 COM 中对象的封送问题,你可以去了解下。

VARIANT vt;

vt.byref = CoTaskMemAlloc(sizeof(MyStruct));

 

struct MySturct{ WCHAR wszStr[200];}

 

Launcher | 园豆:45050 (高人七级) | 2014-07-11 11:30

@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 | 园豆:134 (初学一级) | 2014-07-11 14:01

@Jingle Guo: 

typedef
[
uuid(xxxxx-xxxxx-xxxx--xxxxx),
helpstring("Position Struct")
]
struct Position
{
int x;
int y;
} Position;

Launcher | 园豆:45050 (高人七级) | 2014-07-11 15:02

@Launcher: 

试了,还是不行,难道只能把结构拆开了?

typedef
 [
 uuid(1CED1C51-189B-4A98-98AD-1F8137563571),
 helpstring("Position Struct")
 ]
 struct Position
 {
 int x;
int y;
 } Position;

Jingle Guo | 园豆:134 (初学一级) | 2014-07-11 15:40

@Jingle Guo: 把 struct Position 修改为 struct IPosition,然后作为接口使用。或者把 Position 作为 SAFEARRAY 传递。或者 STDMETHODIMP CFileConvert::ConvertFile(VARIANT * v, LONG* lRet)

Launcher | 园豆:45050 (高人七级) | 2014-07-11 15:51

@Launcher: 

方案1:不知道怎么作为接口使用

方案2和3貌似差不多,都是要把结构体倒腾过去再倒腾回来的样子,算了我还是老老实实的把结构体拆开来传吧。

谢谢您的帮助,感觉耽误了您不少时间的样子。。。

Jingle Guo | 园豆:134 (初学一级) | 2014-07-11 16:28

@Jingle Guo: 有空编写个使用 ADO 更新数据库的代码,你就能理解了。

Launcher | 园豆:45050 (高人七级) | 2014-07-11 16:43
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册