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 применять. Да, надо провайдер ковырять. Имя класса известно.

          Смотрю дамп своей длм-ки, там по каждому объекту такие данные (на примере самого простого):

          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
          т.е. имеется таблица имен свойств-методов + сообщения об ошибках в каждом методе с префиксом $RSLSELFINFO0

          И вот еще - я выше приводил пример вызова метода внешнего объекта из РСЛ:
          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.
            >> Ответить