Re[2]: Передча массива UDT из VB-клиента в ATL-EXE-сервер
От: Rozshnevski Россия  
Дата: 12.01.02 19:15
Оценка:
Здравствуйте VladD2, Вы писали:

VD>1. Proxy/Stub не нужне и даже вреден.


VD>2. Не "MyAtlExe.SendData s()", а "MyAtlExe.SendData s"


VD>3. Массив лучше обявлять динамически:


VD>
VD>dim s() as MyUdt

VD>ReDim s(0 to 10)
VD>


VD>4. В статье http://www.rsdn.ru/article/?com/COMvs.xml
Автор(ы): Чистяков В.Ю.

Эта статья входит в цикл "COM vs. CORBA" и знакомит читателя с основами COM, начиная с интерфейса IUnknown
и заканчивая маршалингом, DCOM и COM+.
дан пример того как это делается.


VD>5. Покажи свое описание (idl) и реализащие метода SendData (ну, и самого интерфейса).


Спасибо, что откликнулись на мой вопрос.

1. Я читал вашу статью, очень полезная. Я хочу пометить что у меня EXE-сервер, может в этом какая-то особенность.
2. Вот мой idl (вроде также как у вас в стотье)
typedef
[
uuid(C21871A0-33EB-11D4-A13A-BE2573A1120F), version(1.0),
helpstring("A UDT variable for VB projects")
]
struct UDTVariable {

BSTR Name;
long Value;

} UDTVariable;

[
object,
uuid(BAFDFAB1-71F9-11D5-A9D2-00A024F25C30),
dual,//oleautomation,//
helpstring("ICoolMsgHandler Interface"),
pointer_default(unique)
]
interface ICoolMsgHandler : IDispatch//IUnknown//
{
.....
[id(3), helpstring("method SendConditionArrays")] HRESULT SendConditionArrays(VARIANT *StateArray, VARIANT *KeyArray, [out, retval] VARIANT_BOOL* bResult);
[id(4), helpstring("method SendData")] HRESULT SendData([in] SAFEARRAY(UDTVariable)* StateArr);
[id(5), helpstring("method M")] HRESULT M([in] long len, [in, size_is(len)] UDTVariable* ssa);
};

-при вызове 4-ой функции из VB возникает ошибка Run-time error 429, ActiveX component cannot create object, при отладке в VC проекте ставил точку останова на самое начало функции но туда управление не дошло, сообщение об ошибке возникало раньше;
-с 5-ой функцией все в порядке (работает если зарегестрировать Proxy/Stub );
-так как 4-ая функция не работает то я попробовал передавать отдельно массив long и BSTR, используя
VARIANT (функция — SendConditionArrays ) здесь все нормально;

3. С++ описания
STDMETHOD(M)(/*[in]*/ long len, /*[in, size_is(len)]*/ UDTVariable* ssa);
STDMETHOD(SendData)(/*[in]*/ SAFEARRAY** StateArr);
STDMETHOD(SendConditionArrays)(VARIANT *StateArray, VARIANT *KeyArray, VARIANT_BOOL* bResult);

......


STDMETHODIMP CCoolMsgHandler::SendConditionArrays(VARIANT *StateArray, VARIANT *KeyArray, VARIANT_BOOL *bResult)
{
long i;
SAFEARRAY FAR* psa = NULL;
SAFEARRAY FAR* pka = NULL;
BSTR HUGEP *pKey;
DWORD HUGEP *pState;
HRESULT hr;
//DWORD dwTimeStart;
LONG cElements, lLBound, lUBound;

// Type check VARIANT parameter. It should contain a BSTR array
// passed by reference. The array must be passed by reference it is
// an in-out-parameter.
if (V_VT(KeyArray) != (VT_ARRAY | VT_BSTR))
return E_INVALIDARG;
if (V_VT(StateArray) != (VT_ARRAY | VT_I4))
return E_INVALIDARG;

psa = V_ARRAY(StateArray);
pka = V_ARRAY(KeyArray);
// Check dimensions of the array.
if (SafeArrayGetDim(psa) != 1)
return E_INVALIDARG;
if (SafeArrayGetDim(pka) != 1)
return E_INVALIDARG;

//dwTimeStart = GetTickCount();

// Get array bounds.
hr = SafeArrayGetLBound(psa, 1, &lLBound);
if (FAILED(hr))
goto error;
hr = SafeArrayGetUBound(psa, 1, &lUBound);
if (FAILED(hr))
goto error;

// Get a pointer to the elements of the array.
hr = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pState);
if (FAILED(hr))
goto error;
hr = SafeArrayAccessData(pka, (void HUGEP* FAR*)&pKey);
if (FAILED(hr))
goto error;


cElements = lUBound-lLBound+1;

........

hr = SafeArrayUnaccessData(pka);
if (FAILED(hr))
goto error;
hr = SafeArrayUnaccessData(psa);
if (FAILED(hr))
goto error;

return S_OK;

error:

return 0;
}

STDMETHODIMP CCoolMsgHandler::SendData(SAFEARRAY **StateArr)
{
.....
return S_OK;
}

STDMETHODIMP CCoolMsgHandler::M(long len, UDTVariable *ssa)
{
.....
return S_OK;
}


4. Вот VB вызовы

////////////////////////////////////////////////////////////////////
Private Sub Command2_Click()
Dim s() As UDTVariable

n = GetTickCount()

i = MsgHndlrInQElCol.Count
If i > 0 Then
ReDim s(i — 1) As UDTVariable
While i > 0
s(i — 1).lState = i
s(i — 1).sKey = "str" + Format(i)
i = i — 1
Wend
MyAtlExe.m MsgHndlrInQElCol.Count, s(0) // работает если зарегестрировать Proxy/Stub
Set MsgHndlrInQElCol = Nothing
End If

m = GetTickCount() — n
Text2.Text = Format(m)
End Sub

////////////////////////////////////////////////////////////////////
Private Sub Command3_Click()
Dim s() As UDTVariable

n = GetTickCount()

i = MsgHndlrInQElCol.Count
If i > 0 Then
ReDim s(i — 1) As UDTVariable
While i > 0
s(i — 1).lState = i
s(i — 1).sKey = "str" + Format(i)
i = i — 1
Wend
Set MsgHndlrInQElCol = Nothing
MyAtlExe.SendData s //возникает ошибка Run-time error 429, ActiveX component cannot create object;
End If

m = GetTickCount() — n
Text3.Text = Format(m)

End Sub


////////////////////////////////////////////////////////////////////
Private Sub Command6_Click()

Dim k As Variant
Dim s As Variant

n = GetTickCount()

i = MsgHndlrInQElCol.Count
If i > 0 Then
ReDim k(i — 1) As String
ReDim s(i — 1) As Long
While i > 0
s(i — 1) = i
k(i — 1) = "str" + Format(i)
MsgHndlrInQElCol.Remove i
i = i — 1
Wend

MyAtlExe.SendConditionArrays s, k //здесь все нормально
End If

m = GetTickCount() — n
Text4.Text = Format(m)
End Sub
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.