Как передать массив объектов (c# .net) в c++ (com)
От: endri  
Дата: 12.10.05 16:32
Оценка:
Господа.

Имеется класс, написанный на c#:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public class UserInfo
{
    private int    _userID        = Null.NullInteger;
    private int    _groupID    = Null.NullInteger;
    private int    _groupTypeID    = Null.NullInteger;
    [MarshalAs(UnmanagedType.BStr)]
    private String    _groupName    = Null.NullString;
    [MarshalAs(UnmanagedType.BStr)]
    private String    _firstName    = Null.NullString;
    [MarshalAs(UnmanagedType.BStr)]
    private string    _lastName    = Null.NullString;
    [MarshalAs(UnmanagedType.BStr)]
    private string    _username    = Null.NullString;
    [MarshalAs(UnmanagedType.BStr)]
    private string    _password    = Null.NullString;
    private bool    _isSuperUser    = Null.NullBoolean;
    [MarshalAs(UnmanagedType.BStr)]
    private string    _universityName = Null.NullString;
}


Так же описан интерфейс для дальнейшего использования в com. В этом интерфейсе есть функция, возвращающая массив объектов UserInfo[].

В tlb формируется следующая структура:


typedef [uuid(8B077412-2955-3343-91FE-A2894BA5FF4F), version(1.0),
custom({0F21F359-AB84-41E8-9A78-36D110E6D2F9}, "NST.BLL.UserInfo")
]
struct tagUserInfo {        
long _userID;       
long _groupID;        
long _groupTypeID;        
BSTR _groupName;        
BSTR _firstName;        
BSTR _lastName;        
BSTR _username;        
BSTR _password;        
long _isSuperUser;        
BSTR _universityName;
} UserInfo;


Функция, возвращающая массив выглядит так:
 [id(0x60020003)]
 HRESULT Users(
               [in] long groupID, 
               [out, retval] SAFEARRAY(UserInfo*)* pRetVal);



Далее в с++ я подключаю com и выполняю следующие действия:


SAFEARRAY* psa;
pITestComponent->Users(1,&psa); // Users - функция, возвращающая массив UserInfo[]

UserInfo* pUserStruct = NULL; // UserInfo - структура, описанная в библиотеке типов(см. выше)
if (psa != NULL)
{     
    hr = SafeArrayAccessData(psa, (void**)&pUserStruct);
    _ASSERT(SUCCEEDED(hr) && pUserStruct);

      // здесь     используем полученный массив структур pUserStruct, но он заполнен  НЕ КОРРЕКТНО

      hr = ::SafeArrayUnaccessData(psa);
    _ASSERT(SUCCEEDED(hr));
}
SafeArrayDestroy(psa);



Проблема в том, что массив pUserStruct в последнем куске кода заполнен не правильно, всякой абракадаброй.
Подскажите, может я что не так делаю?

Заранее благодарю, Андрей.
Re: Как передать массив объектов (c# .net) в c++ (com)
От: endri  
Дата: 12.10.05 20:06
Оценка:
Кстати, можно добавить, что если передавать в COM не массив, а сам объект типа UserInfo, то всё нормально работает. Т.е. структрура типа UserInfo в с++ заполняется без проблем.
Re: Как передать массив объектов (c# .net) в c++ (com)
От: Аноним  
Дата: 12.10.05 22:27
Оценка:
Для просто unmanaged было так: http://www.gotdotnet.ru/Forums/Common/135079.aspx , полное ли соотвествие для СОМ, перед сном не вспомню.
-----
Нулевое оформления постов благодаря Opere.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[2]: Как передать массив объектов (c# .net) в c++ (com)
От: endri  
Дата: 13.10.05 13:18
Оценка:
Здравствуйте, AndroidLV, Вы писали:

ALV>Для просто unmanaged было так: http://www.gotdotnet.ru/Forums/Common/135079.aspx , полное ли соотвествие для СОМ, перед сном не вспомню.


Но это же передача массива структур из c++ DLL в .NET (C#). А мне наоборот нужно.
Re: Как передать массив объектов (c# .net) в c++ (com)
От: GlebZ Россия  
Дата: 13.10.05 14:11
Оценка:
Здравствуйте, endri, Вы писали:


E>Проблема в том, что массив pUserStruct в последнем куске кода заполнен не правильно, всякой абракадаброй.

E>Подскажите, может я что не так делаю?
Попробуй получить через SafeArrayGetElement. Или лучше попробуй посмотреть SafeArrayElemsize. Может он тебе возвращает массив вариантов.

С уважением, Gleb.
Re[2]: Как передать массив объектов (c# .net) в c++ (com)
От: Аноним  
Дата: 13.10.05 14:16
Оценка:
Там в обе стороны описано: http://www.gotdotnet.ru/Forums/Common/135079.aspx#135103 3. пункт заполнение pDataList перед вызовом.
-----
Нулевое оформления постов благодаря Opere.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[3]: Как передать массив объектов (c# .net) в c++ (com)
От: endri  
Дата: 13.10.05 15:18
Оценка:
Здравствуйте, AndroidLV, Вы писали:

ALV>Там в обе стороны описано: http://www.gotdotnet.ru/Forums/Common/135079.aspx#135103 3. пункт заполнение pDataList перед вызовом.


Дело в том, что я пишу в среде c++ и с помощью COM Collable Wrapper подключаюсь к библиотеке, написанной на c#. В c++ я вызываю функцию, описанную в библиотеке типов (TLB), которая возвращает массив структур, формируемых как раз таки в библиотеке .NET.
Приведенный вами вариант мне не подходит, т.к. он нужен для работы в среде .net, с использованием в ней библиотек, написанных на c++. Никакого отношения к com-объектам они не имеют. В этом примере (3 пункт) формируется массив структур для передачи в сишные функции в качестве параметров.

Если я что-то не так понянимаю, поправте, пожалуйста.
Вопрос остается в силе.

С уважением, Андрей
Re[2]: Как передать массив объектов (c# .net) в c++ (com)
От: endri  
Дата: 13.10.05 15:21
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Попробуй получить через SafeArrayGetElement. Или лучше попробуй посмотреть SafeArrayElemsize. Может он тебе возвращает массив вариантов.


Пробовал через SafeArrayGetElement, ничего не вышло, та же беда. SafeArrayElemsize возвращает 4 (это видимо размер указателя на структуру типа UserInfo).
Re[3]: Как передать массив объектов (c# .net) в c++ (com)
От: GlebZ Россия  
Дата: 13.10.05 15:46
Оценка:
Здравствуйте, endri, Вы писали:

E>Пробовал через SafeArrayGetElement, ничего не вышло, та же беда. SafeArrayElemsize возвращает 4 (это видимо размер указателя на структуру типа UserInfo).

Однако в твоем исходном сообщении стоит что это массив структур
UserInfo* pUserStruct = NULL; // UserInfo - структура, описанная в библиотеке типов(см. выше)

Попробуй сделать указатель на массив указателей на структуры
UserInfo** pUserStruct = NULL; // UserInfo - структура, описанная в библиотеке типов(см. выше)


С уважением, Gleb.
Re[4]: Как передать массив объектов (c# .net) в c++ (com)
От: endri  
Дата: 13.10.05 16:01
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Попробуй сделать указатель на массив указателей на структуры

GZ>
GZ>UserInfo** pUserStruct = NULL; // UserInfo - структура, описанная в библиотеке типов(см. выше)
GZ>


Я не совсем понял что мне с этим указателем на массив делать дальше?

Заранее благодарю, Андрей.
Re[5]: Как передать массив объектов (c# .net) в c++ (com)
От: GlebZ Россия  
Дата: 13.10.05 16:12
Оценка:
Здравствуйте, endri, Вы писали:

E>Здравствуйте, GlebZ, Вы писали:


GZ>>Попробуй сделать указатель на массив указателей на структуры

GZ>>
GZ>>UserInfo** pUserStruct = NULL; // UserInfo - структура, описанная в библиотеке типов(см. выше)
GZ>>


E>Я не совсем понял что мне с этим указателем на массив делать дальше?



SAFEARRAY* psa;
pITestComponent->Users(1,&psa); // Users - функция, возвращающая массив UserInfo[]

UserInfo** pUserStruct = NULL; // UserInfo - структура, описанная в библиотеке типов(см. выше)
if (psa != NULL)
{     
    hr = SafeArrayAccessData(psa, (void**)&pUserStruct);
    _ASSERT(SUCCEEDED(hr) && pUserStruct);

      // здесь     используем полученный массив структур pUserStruct, но он заполнен  НЕ КОРРЕКТНО
   long uBound;
   long lBound;
   hresult = SafeArrayGetUBound(psa, 1, &uBound);
   if(FAILED(hresult))
      return hresult;
   hresult = SafeArrayGetLBound(psa, 1, &lBound);
   if(FAILED(hresult))
      return hresult;
     
   for (long i=lBound;l<=uBound;l++)
       MessageBoxW(NULL, (*pUserStruct)->_firstName, L"", MB_OK);

      hr = ::SafeArrayUnaccessData(psa);
    _ASSERT(SUCCEEDED(hr));
}
SafeArrayDestroy(psa);

Так более понятно?

С уважением, Gleb.
Re[6]: Как передать массив объектов (c# .net) в c++ (com)
От: endri  
Дата: 13.10.05 16:19
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>
GZ>SAFEARRAY* psa;
GZ>pITestComponent->Users(1,&psa); // Users - функция, возвращающая массив UserInfo[]

GZ>UserInfo** pUserStruct = NULL; // UserInfo - структура, описанная в библиотеке типов(см. выше)
GZ>if (psa != NULL)
GZ>{     
GZ>    hr = SafeArrayAccessData(psa, (void**)&pUserStruct);
GZ>    _ASSERT(SUCCEEDED(hr) && pUserStruct);

GZ>      // здесь     используем полученный массив структур pUserStruct, но он заполнен  НЕ КОРРЕКТНО
GZ>   long uBound;
GZ>   long lBound;
GZ>   hresult = SafeArrayGetUBound(psa, 1, &uBound);
GZ>   if(FAILED(hresult))
GZ>      return hresult;
GZ>   hresult = SafeArrayGetLBound(psa, 1, &lBound);
GZ>   if(FAILED(hresult))
GZ>      return hresult;
     
GZ>   for (long i=lBound;l<=uBound;l++)
GZ>       MessageBoxW(NULL, (*pUserStruct)->_firstName, L"", MB_OK);

GZ>      hr = ::SafeArrayUnaccessData(psa);
GZ>    _ASSERT(SUCCEEDED(hr));
GZ>}
GZ>SafeArrayDestroy(psa);
GZ>


Всё равно не работает. Структура заполнена неправильно. Все поля типа string = "Bad ptr".
Re[3]: Как передать массив объектов (c# .net) в c++ (com)
От: Аноним  
Дата: 13.10.05 20:37
Оценка:
Мне так показалось, что сам массив структур создается и возвращается из С#, если нет — сорри.
-----
Нулевое оформления постов благодаря Opere.


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.