DLM SDK энумерация свойств
0 (0)
- DLM SDK энумерация свойств ( tema 09.06.2020 23:51 )0(0)Как бы в сишнике получить количество и имена свойств объекта, переданного в качестве параметра?
>> Ответить- Такой объект - наследник TGenObject (+) ( григ 10.06.2020 11:20 )0(0)Точно не скажу, но мысли такие (DLM v 3.08):
! Не каждый объект поддерживает нумерацию свойств и методов.
Есть функция - возвращает количество свойств. Но нет функции, чтобы по индексу получить имя.
// Все объекты для RSL должны наследоваться от TGenObject
typedef struct tagGetObject {struct tagIRslObject *vtbl;} TGenObject;
т.е. TGenObject* extObj=(TGenObject*) v->value.obj;
extObj->vtbl->имя //по идее можно вызвать, что-то из нижеописанного
typedef struct tagIRslObject
{
unsigned size; // Size of this structure
unsigned short (DLMAPIC *AddRef) (TGenObject*);
unsigned short (DLMAPIC *Release) (TGenObject*);
int (DLMAPIC *set) (TGenObject*,char *parm,VALUE *val,long* id);
int (DLMAPIC *setId) (TGenObject*,long id,VALUE *val);
// return: 0 - property, 1 - method, -1 - undefined parameter
int (DLMAPIC *get) (TGenObject*,char *parm,VALUE *val,long* id);
int (DLMAPIC *getId) (TGenObject*,long id,VALUE *val);
int (DLMAPIC *run) (TGenObject*,char *method,long* id);
int (DLMAPIC *runId) (TGenObject*,long id);
// Used by RSL Only
int (DLMAPIC *rslUsed) (TGenObject*);
int (*canCvtToIDispatch) (TGenObject*);
char* (DLMAPIC *typeName) (TGenObject*);
unsigned long (DLMAPIC *typeID) (TGenObject*);
int (DLMAPIC *attach) (TGenObject*,char *method,SYMPROC* sym);
long (*getUniqID) (TGenObject *pObj,char *name);
int (*memberFromID) (TGenObject *pObj,long dispid,long *id);
int (DLMAPIC *tmp1) (void);
void * (DLMAPIC *tmp2) (void);
void * (DLMAPIC *tmp3) (void);
} IRslObject;
и наверное если сделать так, то получим доступ к инфо-данным (не пробовал):
IRslTypeInfo* infObj = (IRslTypeInfo*) v->value.obj
typedef struct
{
unsigned size; // Size of this structure
int (DLMAPIC *isProp) (char *parm,long *id);
int (DLMAPIC *getNProps) (void);
int (DLMAPIC *getNMethods) (void);
int (DLMAPIC *canInherit) (void);
TGenObject* (DLMAPIC *create) (CLNT_PRVD_HANDLE,TGenObject *ctrl);
char* (DLMAPIC *typeName) (void);
} IRslTypeInfo;
Можно попробовать воспользоваться самим РСЛ. В нем есть функция
GenNumProps (obj:object) : integer
Вот пример вызова функции из C++ (можно его переписать):
//Вызов метода внешнего РСЛ-объекта
int TlgFile::GenGetProp(void * ptrObject, string Method)
{SYMPROC * sym;
int IntVal=0;
bool cond;
VALUE parms[2], retVal;
ISYMBOL *symGenRun=lgsymGenGetProp; //ниже коммент - пример, как получить
ValueMake(&retVal);
ValueSet(&retVal,V_INTEGER,&IntVal);
ValueSet(&parms[1],V_GENOBJ,ptrObject);
ValueSet(&parms[0],V_STRING,(char *) Method.c_str());
ADDREF(ptrObject);
//symGenRun=RslGetInstSymbol("GenGetProp");
cond=RslCallInstSymbol(symGenRun, RSL_DISP_GET_OR_RUN, 2, parms, &retVal);
if(cond && retVal.v_type==V_BOOL) IntVal=(int) retVal.value.boolval;
if(cond && retVal.v_type==V_INTEGER) IntVal=retVal.value.intval;
if(cond && retVal.v_type==V_GENOBJ) {IntVal=(int) retVal.value.obj; ADDREF(retVal.value.obj);}
if(cond && retVal.v_type==V_DOUBLE) IntVal=(int) retVal.value.doubval;
ValueClear(&retVal);
ValueClear(&parms[0]);
ValueClear(&parms[1]);
return IntVal;
}
А вот как получить имя по индексу, сходу не скажу. Есть в РСЛ функция PrintProps (object).
Процедура принимает объект в качестве параметра и выводит в стандартный выходной поток для каждого свойства объекта его имя, тип и значение. Но она не выводит индексы. И не со всеми объектами работает.
>> Ответить- Трюк IRslTypeInfo стрёмный какой-то ( tema 15.06.2020 23:10 )0(0)давай по-другому зайду, я расскажу что делал до того как вопрос написать и во что упёрся
свойство можно дёрнуть по имени (get) и по номеру (getId), это я проверял работает. Получить по номеру имя не смог.
Если перебирать номера, пока getId не вернёт -1 то можно получить все значения свойств, но какие имена не понятно. Не работает с TArray, там можно цикл крутить пока PushValue вконец стэк не засрёт.
Пытался дёргать genProc с GOBJ_INITENUM и GOBJ_INITENUM2 — получаю -1 для нескольких разных объектов.((TGenObject *)v->value.obj)->vtbl->genProc((TGenObject *)v->value.obj, GOBJ_INITENUM2, NULL)
IRslTypeInfo* infObj = (IRslTypeInfo*) v->value.obj
если v это VALUE* из GetParm работать не должно, ведь value.obj это TGenObject*, а мы насильно его делаем TGenClass*
Надо из объекта получить класс, как не понял
С реализацией на RSL проблем особых нет, там у меня всё написано, свойства энумеруются. Хотел на C переписать, для ускорения.
Сейчас попробую универсальный провайдер поковырять
>> Ответить- Согласен, IRslTypeInfo (+) ( григ 16.06.2020 09:35 )0(0)неверно к obj применять. Да, надо провайдер ковырять. Имя класса известно.
Смотрю дамп своей длм-ки, там по каждому объекту такие данные (на примере самого простого):
т.е. имеется таблица имен свойств-методов + сообщения об ошибках в каждом методе с префиксом $RSLSELFINFO0
00000732C0: 73 74 21 00 54 4C 47 4C │ 49 53 54 00 24 52 53 4C st! TLGLIST $RSL
00000732D0: 53 45 4C 46 49 4E 46 4F │ 30 00 4E 41 4D 45 00 4F SELFINFO0 NAME O
00000732E0: 42 4A 45 43 54 00 56 41 │ 4C 55 45 00 49 4E 44 45 BJECT VALUE INDE
00000732F0: 58 00 47 45 54 4E 45 58 │ 54 4E 4F 44 45 00 47 45 X GETNEXTNODE GE
0000073300: 54 50 52 45 56 4E 4F 44 │ 45 00 4E 41 4D 45 00 3A TPREVNODE NAME :
0000073310: 20 54 6C 67 4E 6F 64 65 │ 2E 4E 61 6D 65 20 AC AE TlgNode.Name мо
0000073320: A6 AD AE 20 E2 AE AB EC │ AA AE 20 73 74 72 69 6E жно только strin
0000073330: 67 21 00 4F 42 4A 45 43 │ 54 00 56 41 4C 55 45 00 g! OBJECT VALUE
0000073340: 49 4E 44 45 58 00 3A 20 │ 54 6C 67 4E 6F 64 65 2E INDEX : TlgNode.
0000073350: 49 6E 64 65 78 20 AC AE │ A6 AD AE 20 E2 AE AB EC Index можно толь
0000073360: AA AE 20 73 74 72 69 6E │ 67 21 00 4E 41 4D 45 00 ко string! NAME
0000073370: 4F 42 4A 45 43 54 00 56 │ 41 4C 55 45 00 49 4E 44 OBJECT VALUE IND
0000073380: 45 58 00 47 45 54 4E 45 │ 58 54 4E 4F 44 45 00 47 EX GETNEXTNODE G
0000073390: 45 54 50 52 45 56 4E 4F │ 44 45 00 54 6C 67 4E 6F ETPREVNODE TlgNo
00000733A0: 64 65 00 81 A5 A7 20 A8 │ AC A5 AD A8 00 00 00 8D de Без имени Н
00000733B0: A5 E2 20 AF A0 AC EF E2 │ A8 20 A4 AB EF 20 E1 AE ет памяти для со
00000733C0: A7 A4 A0 AD A8 EF 20 54 │ 6C 67 4E 6F 64 65 21 00 здания TlgNode!
00000733D0: 8D A5 E2 20 AF A0 AC EF │ E2 A8 20 A4 AB EF 20 E1 Нет памяти для с
00000733E0: AE A7 A4 A0 AD A8 EF 20 │ 54 6C 67 4E 6F 64 65 21 оздания TlgNode!
00000733F0: 00 8D A5 E2 20 AF A0 AC │ EF E2 A8 20 A4 AB EF 20 Нет памяти для
0000073400: E1 AE A7 A4 A0 AD A8 EF │ 20 54 6C 67 4E 6F 64 65 создания TlgNode
0000073410: 21 00 54 4C 47 4E 4F 44 │ 45 00 24 52 53 4C 53 45 ! TLGNODE $RSLSE
0000073420: 4C 46 49 4E 46 4F 30 00 │ 41 55 54 4F 00 4B 49 4E LFINFO0 AUTO KIN
И вот еще - я выше приводил пример вызова метода внешнего объекта из РСЛ:
cond=RslCallInstSymbol(symGenRun, RSL_DISP_GET_OR_RUN, 2, parms, &retVal);
в RSLDLL.H есть такие константы:
#define RSL_DISP_CTRL -3
#define RSL_DISP_ENUM -4 //вот это интересно попробовать, что будет в retVal?
//задать в parms сам объект и номер 0,1,... - что будет возвращать?
#define RSL_ADVISE -5
#define RSL_UNADVISE -6
#define RSL_DISP_RUN 0
#define RSL_DISP_GET 1
#define RSL_DISP_SET 2
#define RSL_DISP_GET_OR_RUN 3
>> Ответить - Еще раз глянул (+) ( григ 17.06.2020 11:06 )0(0)
vtbl у тебя уже есть - там есть метод:
char* (DLMAPIC *typeName) (TGenObject*);
возвращает имя класса. Это имя юзаем в
typedef IRslTypeInfo* (DLMAPIC *TRslTypeProc) (CLNT_PRVD_HANDLE,const char* typeName);
CLNT_PRVD_HANDLE hndl;
IRslTypeInfo* infoObj = TRslTypeProc (hndl,OBJTYPENAME(v->value.obj)); //получили описание класса
infoObj->getNProps(); //число свойств
infoObj->IsProp(char *parm,long *id); //это у объекта static int DLMAPIC lgNodeFindMember (char *parm,long *id)
static int DLMAPIC lgNodeFindMember (char *parm,long *id)
{ string Prop=parm; Prop.to_upper();
// Индекс не известен
*id=-1;
if (Prop=="NAME") return 1;
if (Prop=="OBJECT") return 1;
if (Prop=="VALUE") return 1;
if (Prop=="INDEX") return 1;
if (Prop=="GETNEXTNODE") return 0;
if (Prop=="GETPREVNODE") return 0;
return -1;
}
Я полагаю, чтобы получить имя по индексу, в последней функции д.б. предусмотрено, что, если задано id и не задано parm, то parm надо заполнить именем. Это уже зависит от реализации самого объекта и нельзя рассчитывать на это.
Кроме того, если объект создан на DLM SDK до 3.14, то у него нет GenProc и GetInterface. Так что всегда юзать GOBJ_INITENUM - не получится. Но, в дампе есть список свойств-методов объекта, значит возможно его получить.
Еще прикольные факты: PrintProps прекрасно работает с TArrray, TBFile, но не работает с TlgList, TlgFile - вылетает. GenNumProps для моих объектов выдает 0, хотя getNProps реализована. Видимо RSL юзает TGenClass с таблицей IRslTypeInfo2. А мои объекты сделаны на DLM SDK 3.08.
>> Ответить- не понял... ( tema 17.06.2020 12:09 )0(0)нет же функции TRslTypeProc, это определяется тип функции
саму функцию пишет разработчик объекта и регистрирует при создании через последний параметр AddObjectProviderModEx.
>> Ответить
- не понял... ( tema 17.06.2020 12:09 )
- Согласен, IRslTypeInfo (+) ( григ 16.06.2020 09:35 )
- Трюк IRslTypeInfo стрёмный какой-то ( tema 15.06.2020 23:10 )
- Такой объект - наследник TGenObject (+) ( григ 10.06.2020 11:20 )