| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > SAFEARRAY внутри SAFEARRAY |
| Автор: Dementor 17.2.2016, 13:15 | ||||||
| Доброго всем дня! Вопрос переехал из темы: http://forum.vingrad.ru/forum/topic-386588.html Что имеем: 1. Имеется структура:
2. Имеется функция:
Массивы Master и Slave заполняются на стороне VBA и содержат внутри себя те же структуры Contour. С ними проблем нет - они адекватно получаются в DLL и адекватно обрабатываются. Проблема возникает в заполнении массива Result. Вот код, который используется для его заполнения:
Поясню для чего я делаю *Result = *Master и NewContour = MasterArray[0].Vertexes: если я все правильно понял из гугления, то для того, что бы легально создать SAFEARRAY, который содержит внутри себя структуру, надо эту самую структуру создавать через IDL, но если честно, то как именно это сделать я не очень понял и поэтому методом проб и ошибок пришел к выводу, что вот подобное работает (в предыдущей версии функции все три массива содержали просто структуры Point3d и Result формировался без каких-либо проблем). А теперь в чем же проблема: после всех операций массив Result содержит нужное количество элементов, однако все элементы одинаковые и равны последнему, который в него передавался. Я пытался вместо SAFEARRAY *NewContour задавать массив Contour с количеством элементов как в Result, заполнять вершинами каждый i-ый элемент и в Result записывать именно i-ый элемент. Но ничего не изменилось. Я конечно понимаю, что я чего-то недопонимаю в самом C++ и SAFEARRAY в частности, но очень прошу помощи в том, что бы разобраться в возникшей проблеме. Заранее всем откликнувшимся огромное спасибо! |
| Автор: xvr 17.2.2016, 15:48 |
Этого делать нельзя. ActiveX подсистема имеет полное право убить Master при возврате из вашего метода и ваш Result повиснет в воздухе. Затем вы пытаетесь записать в SAFEARRAY *Vertexes структуру Point3d. Vertexes на это точно расчитан? |
| Автор: Dementor 17.2.2016, 16:11 | ||
| xvr, хорошо, тогда можем предположить, что никакого Result нет, а результат работы функции я буду записывать в Master, меняя его размер с помощью SafeArrayRedim под нужный мне и далее уже заново заполняя его элементы. Такой подход будет правильным? Что касается SAFEARRAY *Vertexes и Point3d. Т.к. все три массива заведомо создаются на стороне VBA, то там это выглядит так:
Т.е. с моей точки зрения все достаточно правильно. По крайней мере я вижу подтверждение правильности на примере массивов Master и Slave, элементы которых и представляют из себя массивы Point3d. Что касается самой структуры Point3d, то она и в C++ и в VBA состоит из 3-х Double. |
| Автор: Dementor 17.2.2016, 17:11 | ||
Просто ради интереса переделал. Убрал Result, вместо него теперь Master (хотя может это тоже не верно). Ну и перешел с SafeArrayPutElement на работу через SafeArrayAccessData. Но в общем-то ничего и не изменилось в плане результата: теперь уже в Master образуется нужное количество элементов, но каждый элемент равен последнему записанному.
|
| Автор: Dementor 17.2.2016, 17:42 |
| xvr, в общем все заработало. Просто после SafeArrayRedim для главного SAFEARRAY я провел копирование нулевого элемента (который гарантированно всегда есть и который не уничтожается при SafeArrayRedim) во все остальные. Соответственно после этого адекватно проходит SafeArrayRedim для вложенного массива! Может это и костыль и так делать не очень правильно, но по крайней мере работает. У меня остался один вопрос, который я не могу понять. Вот вы пишете, что "ActiveX подсистема имеет полное право убить Master при возврате из вашего метода и ваш Result повиснет в воздухе.", но почему ActiveX убьет массив, который после выполнения неких операций в DLL может еще использоваться в самом VBA? |
| Автор: Dementor 17.2.2016, 18:23 | ||||
| xvr, простите, что достаю вопросами, но сам понять это я не в состоянии и поэтому прошу пояснить. Предположим, что вот это делать нельзя:
Но без этого не выполняется вот это:
И тогда возникает вопрос: если так делать нельзя, то как тогда можно сделать, что бы был корректный результат? Сейчас по крайней мере у меня в VBA после выполнения в функции DLL в массиве Master содержатся все необходимые элементы именно в том виде, в котором они и должны быть... P.S. равно также работает если делать SafeArrayCopy(*Master, Result); и потом уже работать с Result. Поэтому даже вдвойне непонятно - почему это неправильно? |
| Автор: xvr 18.2.2016, 14:15 | ||
Вот как раз так делать можно: SafeArrayCopy(pcnt[0].Vertexes, &pcnt[i].Vertexes). А вот так pcnt[i].Vertexes=pcnt[0].Vertexes - нельзя
Это правильно. А *Result=*Master - нет |
| Автор: Dementor 18.2.2016, 15:15 |
| xvr, спасибо большое за пояснение, а то я думал, что и с таким подходом я не прав. Просто я конечно должен был уточнить, что я имел ввиду под копированием и тогда не было бы недопонимания. Еще раз большое спасибо за помощь и объяснения! |