Идея в том, чтобы во время исполнения программы загружать скомпилированные акторы из известной папки. У меня все акторы являются потомком одного мастер-актора. Это прописано в иерархии класса. Мне не нравится то, как фреймворк плодит кучу классов для ввода-вывода данных, поэтому я сделал мастер-актор, который обеспечивает обмен между всем акторами через тип variant. Проблемы две.
1 Я вызываю nested акторы, предварительно объединив их в массив (скрин 2). При этом в индикаторе appended array 3 мы видим, что выходящий класс превратился в класс мастер-актора (т.е. если бы я все сделал без мастер-актора, то на его месте был бы стандартный класс Actor). Проблема возникает когда я создаю Packed library из nested акторов. Создаю точно такой-же массив как скрине 2 из скомпилированных акторов, но в appended array 3 уже не появляется их общий родительский класс, а появляется стандартный пустой класс (скрин 4). В итоге у меня конфликт типов данных и nested акторы не запускаются.
2 Моя идеология предполагает, что родитель вызывает nested акторы, которых заранее нет в памяти программы. Они должны загружаться из скомпилированных библиотек. Нужные мне vi, которые посылают сообщения и должны выполняться из главного актора, находятся в папке с известным именем. Пока это обычный проект, я могу их найти через стандартную функцию поиска файлов. Но когда это будет скомпилированная библиотека, как их найти?
Загрузка актора на лету
- Juri
- I/O
- Сообщения: 263
- Зарегистрирован: 19 апр 2017, 23:06
- Версия LabVIEW: 2021
- Благодарил (а): 13 раз
- Поблагодарили: 6 раз
Загрузка актора на лету
- Вложения
-
- Рис 2 Массив акторов
- 2.png (11.13 КБ) 2510 просмотров
-
- Рис 3 Мастер-актор
- 3.png (4.95 КБ) 2510 просмотров
-
- Рис 4 Вместо мастер-актора загрузилась пустышка
- 4.png (4.34 КБ) 2510 просмотров
-
IvanLis
- guru
- Сообщения: 5467
- Зарегистрирован: 02 дек 2009, 17:44
- Награды: 7
- Версия LabVIEW: 2015, 2016
- Откуда: СССР
- Благодарил (а): 28 раз
- Поблагодарили: 87 раз
Re: Загрузка актора на лету
Я сам подобного не проделывал, необходимости подобной не было, посмотрите Actor Framework from basic to PPL plugins
Знание нескольких принципов освобождает от знания многих фактов!
Правила форума
Как добавить в сообщение картинку или файл
Конвертация / версий (форматов) VI
Как правильно задать вопрос...
Правила форума
Как добавить в сообщение картинку или файл
Конвертация / версий (форматов) VI
Как правильно задать вопрос...
-
Kosist
- expert
- Сообщения: 1236
- Зарегистрирован: 21 фев 2011, 23:44
- Награды: 2
- Версия LabVIEW: 2013-2020
- Благодарил (а): 23 раза
- Поблагодарили: 30 раз
- Контактная информация:
Re: Загрузка актора на лету
Сначала простая часть - загрузка класса с диска. Для этого есть стандартные функции загрузки класса. Если класс находится в ppl (Project Packed Library), то в палете File I/O -> Advanced File Functions -> Packed Library есть тоже функции которые можно использовать.
Но вот в целом плагиновая архитектура - та еще головная боль.
Тут есть два пути - использовать классы "в сыром виде", или же в виде запакованых библиотек (ppl).
В обох случаях залог успеха - это добиться того, чтобы при динамической загрузке класса в памяти не возникало конфликтов, т.е. нельзя загружать те виайки, которые уже загружены в память самим exe.
Это главная проблема для использования классов "в сыром виде". Достичь этого можно таким способом, что Вы отдельно билдите приложение, и отдельно билдите Source Distribution классов. Но при этом, исключаете из билда все то, что уже включено в билд приложения. В результате, класс после билда обычно нерабочий сам по себе - ведь ему нехватает "общих" виаек с целым приложением.
Другой способ - это ppl. Главный недостаток ppl это то, что их нельзя переносить в другие версии , т.к. по сути это уже скомпилируемый код. Таким образом, сделав проект с использованием ppl, например, в 2018, Вы не откроете его так легко в 2020. Нужно будет билдить опять ppl минимум, а максимум - перелинковывать вручную их в проекте.
Но в случае ppl тоже должно работать правило что общие библиотеки не должны подгружаться многократно. Нужно найти "самостоятельные" библиотеки, которые не зависят от иных библиотек, и билдить ppl сначала с них. Потом - эти библиотеки поменять в коде на ppl, и начать билдить библиотеки которые уже зависят от ppl. При билде нужно ставить галочку Exclude Shared Libraries - таким образом ppl из зависимостей не будет включено в билд этих библиотек. И т.д., идете снизу вверх - сначала "независимые" библиотеки, потом дальше вверх по дереву зависимостей.
Например, LibA содержить класс Shared.lvclass, и LibB тоже использует класс Shared.lvclass. Если просто сбилдить LibA в отдельную ppl, и LibB в отдельную ppl, то обе либки будут содержать класс Shared.lvclass - но для это уже будут разные классы. А вот если сначала в исходнике поместить Shared.lvclass в отдельную либку, из нее сделать ppl, а потом сделать ppl-ки с LibA и LibB (при этом сделать Exclude Shared libs), то уже все будет нормально.
В случае Actor Framework - нужно вначале сбилдить ppl из самой корневой либки Actor Framework, и поменять на нее "исходник" (это, кстати, самое легкое - ПКМ на либке -> Replace by Packed Library). А потом билдить дальше.
Чтобы не возникало конфликтов, разные библиотеки лучше билдить из-под отдельных проектов.
В итоге, Ваше приложение потом будет зависеть от ppl, и Вы сможете сбилдить приложение которое будет их подгружать динамически.
Советую попробовать это сделать на маленьком, пробном проекте - чтобы Вы почувствовали что и как работает. Ну, и менять код на ppl лучше в самом конце, когда проект в исходнике работает полностью. Т.к. дебажить ppl - это то еще удовольствие...
Но вот в целом плагиновая архитектура - та еще головная боль.
Тут есть два пути - использовать классы "в сыром виде", или же в виде запакованых библиотек (ppl).
В обох случаях залог успеха - это добиться того, чтобы при динамической загрузке класса в памяти не возникало конфликтов, т.е. нельзя загружать те виайки, которые уже загружены в память самим exe.
Это главная проблема для использования классов "в сыром виде". Достичь этого можно таким способом, что Вы отдельно билдите приложение, и отдельно билдите Source Distribution классов. Но при этом, исключаете из билда все то, что уже включено в билд приложения. В результате, класс после билда обычно нерабочий сам по себе - ведь ему нехватает "общих" виаек с целым приложением.
Другой способ - это ppl. Главный недостаток ppl это то, что их нельзя переносить в другие версии , т.к. по сути это уже скомпилируемый код. Таким образом, сделав проект с использованием ppl, например, в 2018, Вы не откроете его так легко в 2020. Нужно будет билдить опять ppl минимум, а максимум - перелинковывать вручную их в проекте.
Но в случае ppl тоже должно работать правило что общие библиотеки не должны подгружаться многократно. Нужно найти "самостоятельные" библиотеки, которые не зависят от иных библиотек, и билдить ppl сначала с них. Потом - эти библиотеки поменять в коде на ppl, и начать билдить библиотеки которые уже зависят от ppl. При билде нужно ставить галочку Exclude Shared Libraries - таким образом ppl из зависимостей не будет включено в билд этих библиотек. И т.д., идете снизу вверх - сначала "независимые" библиотеки, потом дальше вверх по дереву зависимостей.
Например, LibA содержить класс Shared.lvclass, и LibB тоже использует класс Shared.lvclass. Если просто сбилдить LibA в отдельную ppl, и LibB в отдельную ppl, то обе либки будут содержать класс Shared.lvclass - но для это уже будут разные классы. А вот если сначала в исходнике поместить Shared.lvclass в отдельную либку, из нее сделать ppl, а потом сделать ppl-ки с LibA и LibB (при этом сделать Exclude Shared libs), то уже все будет нормально.
В случае Actor Framework - нужно вначале сбилдить ppl из самой корневой либки Actor Framework, и поменять на нее "исходник" (это, кстати, самое легкое - ПКМ на либке -> Replace by Packed Library). А потом билдить дальше.
Чтобы не возникало конфликтов, разные библиотеки лучше билдить из-под отдельных проектов.
В итоге, Ваше приложение потом будет зависеть от ppl, и Вы сможете сбилдить приложение которое будет их подгружать динамически.
Советую попробовать это сделать на маленьком, пробном проекте - чтобы Вы почувствовали что и как работает. Ну, и менять код на ppl лучше в самом конце, когда проект в исходнике работает полностью. Т.к. дебажить ppl - это то еще удовольствие...
Мы делили апельсин - много наших полегло...
- Juri
- I/O
- Сообщения: 263
- Зарегистрирован: 19 апр 2017, 23:06
- Версия LabVIEW: 2021
- Благодарил (а): 13 раз
- Поблагодарили: 6 раз
Re: Загрузка актора на лету
Все получилось. Но обнаружилась неприятность. В какой-то момент при переключении с Actor Framework.lvlib на скомпилированный Actor Framework.lvlibp, библиотека AF Debug.lvlib тоже переключается на lvlibp вместо lvlib. Потом когда я возвращаюсь в свой основной проект, в котором продолжаю везде использовать только исходный Actor Framework.lvlib эта AF Debug.lvlib оказывается подключенной к скомпилированной версии Actor Framework.lvlibp и происходит конфликт. Это впрочем никак не мешает исполнению программ. Пока что решил в случае чего хранить всю папку с AF Debug.lvlib в двух архивах один подключен к одной версии Actor Framework другой - к другой и заменять всю папку в случае конфликтов.
- Juri
- I/O
- Сообщения: 263
- Зарегистрирован: 19 апр 2017, 23:06
- Версия LabVIEW: 2021
- Благодарил (а): 13 раз
- Поблагодарили: 6 раз
Re: Загрузка актора на лету
У меня снова проблема. Иерархия наследования на картинке. Actior -> Actors - разные акторы
Actior - Actor Framework, всегда загружается из скомпилированной библиотеки lvlibp
Actors - мое расширение Actor Framework, всегда загружается из скомпилированной библиотеки lvlibp
Pop-up window.class или любой другой на его месте загружаются в режиме отладки из проекта или в режиме исполняемого exe из скомпилированной библиотеки lvlibp.
В Actors у меня происходит загрузка Nested Actors, которые имеют туже самую иерархию. Actors должен знать, работает он из exe или из проекта и в зависимости от этого выбирать способ загрузки Nested Actors (из проекта или из lvlibp) На картинке я это делаю при помощи Conditional Disable Structure. Проблема в том что почему-то она всегда работает в режиме default, даже когда запускается exe. Что я делаю не так? При чем в лаунчере root актора аналогичный кейс работает как надо.
Actior - Actor Framework, всегда загружается из скомпилированной библиотеки lvlibp
Actors - мое расширение Actor Framework, всегда загружается из скомпилированной библиотеки lvlibp
Pop-up window.class или любой другой на его месте загружаются в режиме отладки из проекта или в режиме исполняемого exe из скомпилированной библиотеки lvlibp.
В Actors у меня происходит загрузка Nested Actors, которые имеют туже самую иерархию. Actors должен знать, работает он из exe или из проекта и в зависимости от этого выбирать способ загрузки Nested Actors (из проекта или из lvlibp) На картинке я это делаю при помощи Conditional Disable Structure. Проблема в том что почему-то она всегда работает в режиме default, даже когда запускается exe. Что я делаю не так? При чем в лаунчере root актора аналогичный кейс работает как надо.
-
Kosist
- expert
- Сообщения: 1236
- Зарегистрирован: 21 фев 2011, 23:44
- Награды: 2
- Версия LabVIEW: 2013-2020
- Благодарил (а): 23 раза
- Поблагодарили: 30 раз
- Контактная информация:
Re: Загрузка актора на лету
Это точно что исполняется код в Default структуре, Вы продебажили в exe - или это видно по "косвенным уликам"?
Странно, что typecast исполняется для одного типа класса - этот класс находится в ppl?
Странно, что typecast исполняется для одного типа класса - этот класс находится в ppl?
Мы делили апельсин - много наших полегло...
- Juri
- I/O
- Сообщения: 263
- Зарегистрирован: 19 апр 2017, 23:06
- Версия LabVIEW: 2021
- Благодарил (а): 13 раз
- Поблагодарили: 6 раз
Re: Загрузка актора на лету
Ну на выходе индикатор exe всегда показывает false и nested акторы не загружаются, т.к. включается неверный обработчик их загрузки. Сейчас я решил проблему просто заменив Conditional Disable Structure на кейс структуру.
ps Если что, скрин выше с красной линией - это два разных скрина склеенных вместе.
Actor Framework предоставляет слишком большую свободу в создании разных типов для обмена данными. Я специально ограничил эту свободу тем, что у меня все акторы - потомки класса Actors, который является потомком класса Actor. Потому все Nested акторы загружаются одной единой vi из класса Actors. Все объекты загружаются из lvlibp. PPL в вашем сообщении это какое-то расширение файла или просто аббривеатура Packed Project Library?Странно, что typecast исполняется для одного типа класса - этот класс находится в ppl?
ps Если что, скрин выше с красной линией - это два разных скрина склеенных вместе.
- Juri
- I/O
- Сообщения: 263
- Зарегистрирован: 19 апр 2017, 23:06
- Версия LabVIEW: 2021
- Благодарил (а): 13 раз
- Поблагодарили: 6 раз
Re: Загрузка актора на лету
Периодически у меня получается, что внутри одного актора используются vi из другого актора. В итоге в скомпилированной библиотеке .lvlibp находится второй актор целиком. В ручную я это исправляю легко, но хочется автоматизировать хотябы проверку, чтобы добавить Pre-Build Action, который будет проверять, не попадаются ли vi из чужого актора. Как сделать такую проверку?
UPD: нашел решение. Потом выложу
UPD: нашел решение. Потом выложу