использование VARIANT SAFEARRAY

 
0
 
C++
ava
елки | 11.12.2016, 19:43
Всем привет. Сейчас работаю с некоторой динамической библиотекой(*.dll). Пытаюсь из этой dll использовать  некую функцию GetTitleIDList. Прототип функции в Visual C++ выглядит так GetTitleIDList(VARIANT_BOOL , int, int, int*, VARIANT*,VARIANT*).
В документации к  dll эта функция описывается так:
    This method retrieves two arrays which contain the IDs and titles of all entities (in the selected ID range) with the same type as the current object. GetTitleIDList( bIncludeID, minID, maxID, count, listID, listTITLE )Input: 
  •  BOOL bIncludeID If True, the  titles are in the form “ID..title” (for example, “1..Steel”. If False, only the title, without the ID or separator is returned. 
  •  INT4 minID The minimum and maximum entity IDs to retrieve. You can set  minID=maxID=0 to retrieve all available entities.  
  •  INT4 maxIDOutput: 
  •  INT4 count The number of entities retrieved. This is the number of entries in listID and listTITLE. 
  •  INT4 listID[0..count-1] The IDs of the available entities. STRING listTITLE[0..count-1] The titles of the available entities. If the entity does not have a title, the string “Untitled” will be returned. Return Code: 
  • [FE_FAIL=0 FE_OK=-1  This function is only available for entity types that have titles (Mate­rial, Property, View, etc)
В документации приведен пример на Visual BAsic

‘Attach to FEMAP........................
Dim femap As Object
Set femap = GetObject(, "femap.model")

‘Look at Output Set 3...................
Dim oc As Object
Set oc = femap.feOutputSet()
oc.Get (3)
Dim od As Object
Set od = oc.Vector(1)

Dim rc As Integer
Dim Count As Long
Dim ID As Variant
Dim Title As Variant
Dim Row As Integer

‘Retrieve ID and Title of all available Output Vectors...
rc = od.GetTitleIDList(False, 0, 0, Count, ID, Title)
‘ Display list in cells of a spreadsheet.................
For Row = 1 To Count
  Worksheets(1).Cells(Row, 1).Value = ID(Row - 1)
  Worksheets(1).Cells(Row, 2).Value = Title(Row - 1)
Next Row

Теперь как я пытаюсь это использовать.

        int count;
    SAFEARRAY *TitleArray;
    SAFEARRAY *IDArray;
        BSTR str;
    TitleArray=SafeArrayCreateVector(VT_BSTR,0,9);
    IDArray=SafeArrayCreateVector(VT_I4,0,9);
         if(TitleArray==0)return 0;
    if(IDArray==0)return 0;
        if(pEntity->GetTitleIDList(true,0,0, &count,  (VARIANT*) IDArray, (VARIANT*) TitleArray)==-1){
        for (long i=0; i<count;i++){
             if(SafeArrayGetElement(TitleArray,&i,&str){
                MessageBox(0,str,str,0); // в этом месте планировалось вызвать SendMessage(hList, LB_ADDSTRING,0, (LPARAM)str); 
              }      
            }
       }
 В сообщении MessageBox выводятся иероглифы вместо строк на английском языке.
пробовал использовать VARIANT

        VARIANT ListTitle
        int count;
    SAFEARRAY *TitleArray;
    SAFEARRAY *IDArray;
        BSTR str;
    TitleArray=SafeArrayCreateVector(VT_BSTR,0,9);
    IDArray=SafeArrayCreateVector(VT_I4,0,9);
         if(TitleArray==0)return 0;
    if(IDArray==0)return 0;
        ListTitle.vt=VT_ARRAY|VT_BSTR;
        ListTitle.parray=TitleArray;
        if(pEntity->GetTitleIDList(true,0,0, &count,  (VARIANT*) IDArray,  ListTitle)==-1){
        for (long i=0; i<count;i++){
              //тут пока не понятно как из VARIANT ListTitle извлечь массив строк и вывести их хотя бы в MessageBox
              }      
            }
       }

Подскажите в чём моя ошибка и как лучше исправить?
Kommentare (14)
ava
feodorv | 11.12.2016, 20:56 #
А что у Вас с UNICODE?
ava
елки | 11.12.2016, 21:11 #
Цитата (feodorv @  11.12.2016,  20:56 findReferencedText)
А что у Вас с UNICODE? 

Я специально никакие настройки  не выставлял. Часть проекта автоматически сгенирирована в visual studio 2010.
ava
feodorv | 11.12.2016, 21:22 #
Ну так у Вас по умолчанию может быть выставлено UNICODE, а GetTitleIDList() может возвращать простое ASCII. Вот у Вас и иероглифы в MessageBox().

PS Такое возможно, но не обязательно. Но не мешает проверить)))

später ergänzt:
Попробуйте MessageBoxA().
ava
елки | 11.12.2016, 21:53 #
feodorv, попробовал не получилось. думаю дело не в кодировке. предпоследнее значение в этой функции вообще целое число и тоже не хочет выводиться. пробовал вот такой код.

long n=-1;
for(long i-0;i<count;i++)
if(SafeArrayGetElement(IDArray,&i,&n)){
почему-то получается, что n так и остается -1 и никак не меняется. ну, если поставлю n=-10, то так и останется -10...
}
ava
vol4ek | 11.12.2016, 23:10 #
не увидел функции VariantInit
ava
миг | 12.12.2016, 06:46 #
VariantInit - устанавливает флаг VT_EMPTY Это означает пустой вариант. Если хотим поместить данные, то должны изменить флаг VT_тип данных которые нужно поместить в вариант. Можно теоретически сделать пустой вариант и пусть функция GetTitleIdList сама попробует установить ей нужный флаг и записать данные.
ava
vol4ek | 12.12.2016, 08:47 #
Цитата (миг @ 12.12.2016,  06:46)
VariantInit - устанавливает флаг VT_EMPTY. Можно теоретически сделать пустой вариант и пусть функция GetTitleIdList сама попробует установить ей нужный флаг и записать данные.

я всегда так и делал и проблем с этим типом никогда небыло.
ava
feodorv | 12.12.2016, 09:22 #
А я вот соглашусь с vol4ek. Как-то это все жестко выглядит:
Цитата (елки @  11.12.2016,  19:43 findReferencedText)
(VARIANT*) IDArray, (VARIANT*) TitleArray)

Я так понимаю, что в GetTitleIDList() отправляются пустые VARIANT, а возвращаются заполненные, которые потом высвобождать нужно будет.
ava
миг | 12.12.2016, 09:57 #
vol4ek, VariantInit эквивалентно записи

VARIANT t;
t.vt=VT_EMPTY;

А если известно какие типы данных будут хранится в переменной, то почему нельзя сразу записать t.vt=VT_ARRAY и т.д.? Другое дело вызываемая функция могла установить другой флаг.

später ergänzt:
Цитата (feodorv @  12.12.2016,  09:22 findReferencedText)
Я так понимаю, что в GetTitleIDList() отправляются пустые VARIANT, а возвращаются заполненные, которые потом высвобождать нужно будет. 

Да именно так. Если верить описанию этой функции.
ava
vol4ek | 12.12.2016, 11:39 #
Цитата (миг @ 12.12.2016,  09:57)
vol4ek, VariantInit эквивалентно записи


VARIANT t;

t.vt=VT_EMPTY;



А если известно какие типы данных будут хранится в переменной, то почему нельзя сразу записать t.vt=VT_ARRAY и т.д.? Другое дело вызываемая функция могла установить другой флаг.



später ergänzt:

Цитата (feodorv @  12.12.2016,  09:22 findReferencedText)
Я так понимаю, что в GetTitleIDList() отправляются пустые VARIANT, а возвращаются заполненные, которые потом высвобождать нужно будет. 


Да именно так. Если верить описанию этой функции.

я вкурсе чем занимается VariantInit() и думаю с флагом VT_EMPTY и надо работать. пусть GetTitleIDList сама ставит нужные флаги. Наврятли функцию инициализации зря придумали.
ava
елки | 12.12.2016, 21:51 #
vol4ek, вот если написать так

VARIANT* var1;
VARIANT* var2;
VariantInit(var1);
VariantInit(var2);
int count;
pEntity->GetTitleIDList(true,0,0,&count, var1, var2);

то при вызове функции программа падает и запускается отладчик.
ava
елки | 12.12.2016, 22:23 #
Всем спасибо. у меня наконец-то получилось, то что нужно.

int count;
VARIANT listTitle;
SAFEARRAY *IDArray;
SAFEARRAY* Test;
BSTR str;
IDArray=SafeArrayCreateVector(VT_I4,0,9);
if(pEntity->GetTitleList(true, 0, 0, &count, (VARIANT*) IDArray, &listTitle)==-1){
  for(long i=0; i<count; i++){
      Test=listTitle.parray;
       if(!SafeArrayGetElement(Test,&i,&str)) MessageBox(0,str,str,0);
}
}
ava
xvr | 13.12.2016, 10:53 #
Неправильно. Работает у вас чисто случайно - места в IDArray хватило на VARIANT и вы его (IDArray) потом не используете
Вариант из предыдущего сообщения был почти правильный. Надо так:

VARIANT var1;
VARIANT var2;
VariantInit(&var1);
VariantInit(&var2);
int count;
pEntity->GetTitleIDList(true,0,0,&count, &var1, &var2);
ava
миг | 27.12.2016, 11:24 #
Кстати можно еще использовать 


CComVariant var1

Но VARIANT тоже сработает
Registrieren Sie sich oder melden Sie sich an, um schreiben zu können.
Unternehmen des Tages
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Mitwirkende
  xvr   миг   vol4ek ava  feodorv   елки
advanced
Absenden