Как создавать методы с необязательными параметрами
От: tamtam  
Дата: 08.06.02 16:36
Оценка:
Очень часто видел такие медоды, например в ADO
А как самому такие сделать в COM что-то не догоняю...
Помогите.
Re: Как создавать методы с необязательными параметрами
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.06.02 14:07
Оценка: 6 (1)
Здравствуйте tamtam, Вы писали:

T>Очень часто видел такие медоды, например в ADO

T>А как самому такие сделать в COM что-то не догоняю...
T>Помогите.

Если параметр имеет тип VARIANT, то помечаешь его атрибутом optional.
Если другой, помечаешь его атрибутом defaultvalue(Значение). Где "Значение" — это значение которое будет подставляться по умолчанию.

При этом есть два ограничения. Не обязательные параметры дожны идти в конце (т.е. с правой стороны) списка параметров (но перед [out, retval]).

Значения по умолчанию будут доступны только в высокоуровневых языках/визуальных средах (типа VB). В VC можно воспользоваться директивой #import, которая (по умолчанию) создает обертки над COM-интерфейсами обеспечивающие такую функциональность.

Вот пример idl-я:

HRESULT SomeMethod([in], NormalParam, [in, optional] VARIANT OptionalParam, [in, defaultvalue(-1)] long DefValParam, [out, retval] long *pRet);


PS

На этот вопрос сдесь отвечали уже много раз. На будущее советую сначала воспользоваться поиском.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Как создавать методы с необязательными параметрами
От: tamtam  
Дата: 10.06.02 04:29
Оценка:
Здравствуйте VladD2.

Спасибо за ответ.
Я именно так и делаю, но при вызове из VBS или JS идет ошибка — неверное кол-во параметров или их типы.
ВОт сижу и думаю, что сделал неправильно...

Но всеравно спасибо. Кстати, как искоть в этом форуме? Не догоняю...
Re[3]: Как создавать методы с необязательными параметрами
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.06.02 11:28
Оценка:
Здравствуйте tamtam, Вы писали:

T>Здравствуйте VladD2.


T>Спасибо за ответ.

T>Я именно так и делаю, но при вызове из VBS или JS идет ошибка — неверное кол-во параметров или их типы.

Объявляй параметры методов как VARIANT, тогда пробем со скриптами будет меньше.

T>Но всеравно спасибо. Кстати, как искоть в этом форуме? Не догоняю...


Дык на любой (если ты конечно не лазиешь напрямую в форумы) странице в шапке есть кнопка.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Как создавать методы с необязательными параметрами
От: tamtam  
Дата: 10.06.02 17:15
Оценка:
Здравствуйте VladD2.

Вот как я объявляю

__interface IMyInterface : IDispatch
{
....
[id(6), helpstring("method Method1")] HRESULT Method1([in, optional] VARIANT p1, [in, optional] VARIANT p2);
...
};


class ATL_NO_VTABLE CMyInterface :
public MyInterface
{
...
public:
...
STDMETHOD(Method1)(VARIANT p1, VARIANT p2);
...
};


Может подскажете, где у меня клинит?
Re[5]: Как создавать методы с необязательными параметрами
От: tamtam  
Дата: 10.06.02 17:19
Оценка:
Ну а вызываю соответственно:

var o = WScript.CreateObject("MyObject.MyInterface")
o.Method1()
Re[5]: Как создавать методы с необязательными параметрами
От: George_Seryakov Россия  
Дата: 10.06.02 19:03
Оценка:
Здравствуйте tamtam, Вы писали:

TT>[id(6), helpstring("method Method1")] HRESULT Method1([in, optional] VARIANT p1, [in, optional] VARIANT p2);


T>Может подскажете, где у меня клинит?


Будем проверять дальше.

1. Найди длл (или ехе), в который линкуется, проверь tlb в этом исполняемом, что там есть такое же объявление,
2. Проверь, что зарегистрировано в качестве tlb для твоего интерфейса, тот ди файд, что линкуется.

Могут быть глюки с невозможностью перевисать исполняемый файл (залочен) и тем, что компонент не регистрирует новый интерфейс из-за программной ощибки,
GS
Re[2]: optional и defaultvalue
От: Vi2 Удмуртия http://www.adem.ru
Дата: 11.06.02 03:57
Оценка:
Здравствуйте VladD2, Вы писали:

VD>Если параметр имеет тип VARIANT, то помечаешь его атрибутом optional.

VD>Если другой, помечаешь его атрибутом defaultvalue(Значение). Где "Значение" — это значение которое будет подставляться по умолчанию.

optional не применяется к параметрам, не имеющим тип VARIANT или VARIANT*. Однако defaultvalue(Значение) применяется к любым, даже и имеющим тип VARIANT.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[3]: optional и defaultvalue
От: tamtam  
Дата: 11.06.02 13:03
Оценка:
Все проверил, все нормально. в ТЛБешке все как надо
HRESULT Method([in, optional] VARIANT p1, [in, optional] VARIANT p2);

сам теряюсь в догадках
Re[4]: Dispatch реализация
От: Vi2 Удмуртия http://www.adem.ru
Дата: 11.06.02 13:13
Оценка:
Здравствуйте tamtam, Вы писали:

T>Все проверил, все нормально. в ТЛБешке все как надо

T> HRESULT Method([in, optional] VARIANT p1, [in, optional] VARIANT p2);

T>сам теряюсь в догадках


Судя по твоему предыдущему письму
__interface IMyInterface : IDispatch 
{ 
.... 
[id(6), helpstring("method Method1")] HRESULT Method1([in, optional] VARIANT p1, [in, optional] VARIANT p2); 
... 
}; 

class ATL_NO_VTABLE CMyInterface : 
public MyInterface 
{ 
... 
public: 
... 
STDMETHOD(Method1)(VARIANT p1, VARIANT p2); 
... 
};


Не мог бы ты показать как у тебя реализуются IDispatch функции — GetTypeInfoCount, GetTypeInfo, GetIDsOfNames, Invoke? И что такое __interface? И что такое MyInterface?
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[3]: optional и defaultvalue
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.06.02 14:13
Оценка:
Здравствуйте Vi2, Вы писали:

Vi2>optional не применяется к параметрам, не имеющим тип VARIANT или VARIANT*. Однако defaultvalue(Значение) применяется к любым, даже и имеющим тип VARIANT.


А ты попробуй.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Сморозил глупость
От: Vi2 Удмуртия http://www.adem.ru
Дата: 11.06.02 14:41
Оценка:
Здравствуйте VladD2, Вы писали:

Vi2>>optional не применяется к параметрам, не имеющим тип VARIANT или VARIANT*. Однако defaultvalue(Значение) применяется к любым, даже и имеющим тип VARIANT.


VD>А ты попробуй.


Да... Сморозил глупость. Не даёт MIDL задать defaultvalue для VARIANT.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[5]: Dispatch реализация
От: tamtam  
Дата: 11.06.02 16:53
Оценка:
Здравствуйте Vi2, Вы писали:

Vi2>Не мог бы ты показать как у тебя реализуются IDispatch функции — GetTypeInfoCount, GetTypeInfo, GetIDsOfNames, Invoke? И что такое __interface? И что такое MyInterface?


Пишу я на VS.NET (ATL 7.0)
И все это генерируется автоматически.
Прошагал вызов в отладчике на Invoke и нашел там код который жестко проверяет кол-во параметров независимо от того, optional они или defaultvalue.
как заставить нормальный код генерировать мне непонятно.

вот что лежит в MyInterface.H файле
// IMyInterface
[
object,
uuid("9E3B7F38-3953-4AA8-AA8C-B51084DAC59B"),
dual, helpstring("IMyInterface Interface"),
pointer_default(unique)
]
__interface IMyInterface : IDispatch
{
[id(1), helpstring("method Method1")] HRESULT Method1([in] VARIANT p1, [in, optional] VARIANT p2, [out,retval] LONG* p3);
[id(2), helpstring("method Method2")] HRESULT Method2([in, defaultvalue(0)] LONG p1);
};

// CMyInterface

[
coclass,
threading("single"),
vi_progid("MyObject.MyInterface"),
progid("MyObject.MyInterface.1"),
version(1.0),
uuid("341D3D93-EFED-4487-A4CE-724E8CFC2D4B"),
helpstring("MyInterface Class")
]

а вот что выловил в отладчике
1:
2: //+++ Start Injected Code For Attribute 'coclass'
3: #injected_line 31 "d:\\documents and settings\\tyra\\my documents\\visual studio projects\\citkeygen\\myinterface.h"
4: virtual HRESULT STDMETHODCALLTYPE IMyInterface::Invoke(
5: /* [in] */ DISPID dispIdMember,
6: /* [in] */ REFIID riid,
7: /* [in] */ LCID lcid,
8: /* [in] */ WORD wFlags,
9: /* [out][in] */ DISPPARAMS *pDispParams,
10: /* [out] */ VARIANT *pVarResult,
11: /* [out] */ EXCEPINFO *pExcepInfo,
12: /* [out] */ UINT *puArgErr)
13: {
14: (void) riid;
15: (void) dispIdMember;
16: (void) lcid;
17: (void) wFlags;
18: (void) pExcepInfo;
19: (void) puArgErr;
20: HRESULT hr = S_OK;
21: if (pDispParams == 0) {
22: return DISP_E_BADVARTYPE;
23: }
24: if (pDispParams->cArgs > 3) {
25: return DISP_E_BADPARAMCOUNT;
26: }
27: if (pVarResult != 0) {
28: ::VariantInit(pVarResult);
29: }
30: VARIANT* rgpVars[3];
31: UINT index = 0;
32: if (pDispParams->cNamedArgs > 0) {
33: if (pDispParams->rgdispidNamedArgs[0] == DISPID_PROPERTYPUT) {
34: rgpVars[0] = &pDispParams->rgvarg[0];
35: index = 1;
36: }
37: for (; index < pDispParams->cNamedArgs; ++index) {
38: if (pDispParams->rgdispidNamedArgs[index] >= (int) pDispParams->cArgs || pDispParams->rgdispidNamedArgs[index] < 0) {
39: if (puArgErr != 0) {
40: *puArgErr = index;
41: }
42: return DISP_E_PARAMNOTFOUND;
43: }
44: rgpVars[pDispParams->cArgs — pDispParams->rgdispidNamedArgs[index] — 1] = &pDispParams->rgvarg[index];
45: }
46: }
47: for (; index < pDispParams->cArgs; ++index) {
48: rgpVars[index] = &pDispParams->rgvarg[index];
49: }
50: VARIANT v0;
51: VARIANT* v;
52: switch (dispIdMember) {
53: case 1:// Method1
54: {
55: if (pDispParams->cArgs != 2) { // должено быть два аргумента!!!!

56: return DISP_E_BADPARAMCOUNT;
57: }
58: v = rgpVars[1];
59: if (v->vt == (VT_VARIANT | VT_BYREF)) {
60: v = V_VARIANTREF(v);
61: }
62: VARIANT i1 = *v;
63: v = rgpVars[0];
64: if (v->vt == (VT_VARIANT | VT_BYREF)) {
65: v = V_VARIANTREF(v);
66: }
67: VARIANT i2 = *v;
68: long i3;
69: hr = ((::IMyInterface*) this)->Method1(i1, i2, &i3);
70: if (pVarResult != 0) {
71: V_VT(pVarResult) = VT_I4;
72: V_I4(pVarResult) = i3;
73: }
74: break;
75: }
76: case 2: // Method2
77: {
78: if (pDispParams->cArgs != 1) { // должен быть один аргумент!!!
79: return DISP_E_BADPARAMCOUNT;
80: }
81: v = rgpVars[0];
82: if (v->vt != VT_I4 && FAILED(__VariantChangeType(v, &v0, VT_I4))) {
83: if (puArgErr != 0) {
84: *puArgErr = 0;
85: }
86: return DISP_E_TYPEMISMATCH;
87: }
88: long i1 = V_I4(v);
89: hr = ((::IMyInterface*) this)->Method2(i1);
90: break;
91: }
92: default:
93: return DISP_E_MEMBERNOTFOUND;
94: }
95: return hr;
96: }
Re[4]: optional и defaultvalue
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.06.02 19:54
Оценка:
Здравствуйте tamtam, Вы писали:

T>Все проверил, все нормально. в ТЛБешке все как надо

T> HRESULT Method([in, optional] VARIANT p1, [in, optional] VARIANT p2);

T>сам теряюсь в догадках


Что проверил? Что нормальн? Ты вот так попробуй:
HRESULT Method([in, defaultvalue("Вот такой вот дефолт!")] VARIANT p1, [in, defaultvalue(-21)] VARIANT p2);


А то, что optional для вариантов подходит, ... кто бы спорил.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: optional и defaultvalue
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.06.02 19:55
Оценка:
Здравствуйте tamtam, Вы писали:

Или, это я не в кассу.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Как создавать методы с необязательными параметрами
От: tamtam  
Дата: 12.06.02 09:27
Оценка:
Всем привет.
Вроде нащупал проблему.

Я при создании ATL проекта в VS.NET выбрал галочку "Atributed" если ее не ставить, все поулчается нормально. Пошел разбираться, что за атрибутед такие.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.