Oleg: Для VT_BSTR надо как-то так: byte* bytePtr3 = stackalloc byte[sizeof(uint)];
PDLCSGetPropertyEx(bytePtr3);
var ptrBSTR = new IntPtr((uint*)bytePtr3[0]);
var bstr = Marshal.PtrToStringBSTR(ptrBSTR);
Marshal.FreeBSTR(ptrBSTR); BSTR это особый тип данных, для хранения строки там выделяется место COM библиотекой, и удаляться должно тоже ей. Поэтому там указатель на данные. А это 4 байта
Oleg: Мои предположения верны. Функция хочет получать адрес на выделенную память, чтобы туда записать значение. Для VT_I4 ждет 4 байта, под VT_R8 ждет 8 байт. Для VT_BSTR - 4 байта. Тут ref не нужен, тут достаточно просто указателя. Т.е. выделив byte* bytePtr3 = stackalloc byte[sizeof(double)]; и затем double* value = (double*)bytePtr3; в value[0] будет ваше значение.
Oleg: А у вас есть пример вызова этой функции на С++? Мои соображения, что 0x00000050 является явно не валидным адресом, может тут возвращается не указатель, а само число?
angelzzz: Так для этого и проводятся собеседования и тестовые задания, чтобы проверить знания и опыт, добросовестность выполнения. Еще есть испытательный срок.
Oleg: Это зависит от того, что вы ждете в ответ. Если обычные данные, то можно и на стеке выделить память byte* bytePtr3 = stackalloc byte[chcount * sizeof(uint)]; Либо через Pinned object - Пример: localArray = Array.CreateInstance(type, (countOnElement > 1) ? new int[1] { (int)size.Length * countOnElement } : size.ToIntArray());
handle = GCHandle.Alloc(localArray, GCHandleType.Pinned);
handle.AddrOfPinnedObject(); А вот если там требуется обьект типа VARIANT, то и третьим способом, так как там обьекты инициализируются и удаляются через нативную COM библиотеку.
Oleg: Да, посмотрел внимательнее, ref в вашем случае не нужен, у вас ведь CMN_ERROR *pError, а не CMN_ERROR **pError. Может стоит и [MarshalAs(UnmanagedType.LPStruct)] убрать?