Страница 1 из 1

Загрузка актора на лету

Добавлено: 22 дек 2020, 19:47
Juri
Идея в том, чтобы во время исполнения программы загружать скомпилированные акторы из известной папки. У меня все акторы являются потомком одного мастер-актора. Это прописано в иерархии класса. Мне не нравится то, как фреймворк плодит кучу классов для ввода-вывода данных, поэтому я сделал мастер-актор, который обеспечивает обмен между всем акторами через тип variant. Проблемы две.
1 Я вызываю nested акторы, предварительно объединив их в массив (скрин 2). При этом в индикаторе appended array 3 мы видим, что выходящий класс превратился в класс мастер-актора (т.е. если бы я все сделал без мастер-актора, то на его месте был бы стандартный класс Actor). Проблема возникает когда я создаю Packed library из nested акторов. Создаю точно такой-же массив как скрине 2 из скомпилированных акторов, но в appended array 3 уже не появляется их общий родительский класс, а появляется стандартный пустой класс (скрин 4). В итоге у меня конфликт типов данных и nested акторы не запускаются.
2 Моя идеология предполагает, что родитель вызывает nested акторы, которых заранее нет в памяти программы. Они должны загружаться из скомпилированных библиотек. Нужные мне vi, которые посылают сообщения и должны выполняться из главного актора, находятся в папке с известным именем. Пока это обычный проект, я могу их найти через стандартную функцию поиска файлов. Но когда это будет скомпилированная библиотека, как их найти?

Re: Загрузка актора на лету

Добавлено: 22 дек 2020, 20:45
IvanLis
Я сам подобного не проделывал, необходимости подобной не было, посмотрите Actor Framework from basic to PPL plugins

Re: Загрузка актора на лету

Добавлено: 22 дек 2020, 22:48
Kosist
Сначала простая часть - загрузка класса с диска. Для этого есть стандартные функции загрузки класса. Если класс находится в ppl (Project Packed Library), то в палете File I/O -> Advanced File Functions -> Packed Library есть тоже функции которые можно использовать.
Но вот в целом плагиновая архитектура - та еще головная боль.
Тут есть два пути - использовать классы "в сыром виде", или же в виде запакованых библиотек (ppl).
В обох случаях залог успеха - это добиться того, чтобы при динамической загрузке класса в памяти не возникало конфликтов, т.е. нельзя загружать те виайки, которые уже загружены в память самим exe.
Это главная проблема для использования классов "в сыром виде". Достичь этого можно таким способом, что Вы отдельно билдите приложение, и отдельно билдите Source Distribution классов. Но при этом, исключаете из билда все то, что уже включено в билд приложения. В результате, класс после билда обычно нерабочий сам по себе - ведь ему нехватает "общих" виаек с целым приложением.
Другой способ - это ppl. Главный недостаток ppl это то, что их нельзя переносить в другие версии :labview: , т.к. по сути это уже скомпилируемый код. Таким образом, сделав проект с использованием ppl, например, в :labview: 2018, Вы не откроете его так легко в :labview: 2020. Нужно будет билдить опять ppl минимум, а максимум - перелинковывать вручную их в проекте.
Но в случае ppl тоже должно работать правило что общие библиотеки не должны подгружаться многократно. Нужно найти "самостоятельные" библиотеки, которые не зависят от иных библиотек, и билдить ppl сначала с них. Потом - эти библиотеки поменять в коде на ppl, и начать билдить библиотеки которые уже зависят от ppl. При билде нужно ставить галочку Exclude Shared Libraries - таким образом ppl из зависимостей не будет включено в билд этих библиотек. И т.д., идете снизу вверх - сначала "независимые" библиотеки, потом дальше вверх по дереву зависимостей.
Например, LibA содержить класс Shared.lvclass, и LibB тоже использует класс Shared.lvclass. Если просто сбилдить LibA в отдельную ppl, и LibB в отдельную ppl, то обе либки будут содержать класс Shared.lvclass - но для :labview: это уже будут разные классы. А вот если сначала в исходнике поместить Shared.lvclass в отдельную либку, из нее сделать ppl, а потом сделать ppl-ки с LibA и LibB (при этом сделать Exclude Shared libs), то уже все будет нормально.
В случае Actor Framework - нужно вначале сбилдить ppl из самой корневой либки Actor Framework, и поменять на нее "исходник" (это, кстати, самое легкое - ПКМ на либке -> Replace by Packed Library). А потом билдить дальше.
Чтобы не возникало конфликтов, разные библиотеки лучше билдить из-под отдельных проектов.
В итоге, Ваше приложение потом будет зависеть от ppl, и Вы сможете сбилдить приложение которое будет их подгружать динамически.
Советую попробовать это сделать на маленьком, пробном проекте - чтобы Вы почувствовали что и как работает. Ну, и менять код на ppl лучше в самом конце, когда проект в исходнике работает полностью. Т.к. дебажить ppl - это то еще удовольствие...

Re: Загрузка актора на лету

Добавлено: 05 фев 2021, 13:23
Juri
Все получилось. Но обнаружилась неприятность. В какой-то момент при переключении с 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 другой - к другой и заменять всю папку в случае конфликтов.

Re: Загрузка актора на лету

Добавлено: 17 май 2021, 13:33
Juri
У меня снова проблема. Иерархия наследования на картинке. 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 актора аналогичный кейс работает как надо.

Re: Загрузка актора на лету

Добавлено: 17 май 2021, 15:52
Kosist
Это точно что исполняется код в Default структуре, Вы продебажили в exe - или это видно по "косвенным уликам"?
Странно, что typecast исполняется для одного типа класса - этот класс находится в ppl?

Re: Загрузка актора на лету

Добавлено: 18 май 2021, 09:52
Juri
Ну на выходе индикатор exe всегда показывает false и nested акторы не загружаются, т.к. включается неверный обработчик их загрузки. Сейчас я решил проблему просто заменив Conditional Disable Structure на кейс структуру.
Странно, что typecast исполняется для одного типа класса - этот класс находится в ppl?
Actor Framework предоставляет слишком большую свободу в создании разных типов для обмена данными. Я специально ограничил эту свободу тем, что у меня все акторы - потомки класса Actors, который является потомком класса Actor. Потому все Nested акторы загружаются одной единой vi из класса Actors. Все объекты загружаются из lvlibp. PPL в вашем сообщении это какое-то расширение файла или просто аббривеатура Packed Project Library?

ps Если что, скрин выше с красной линией - это два разных скрина склеенных вместе.

Re: Загрузка актора на лету

Добавлено: 11 май 2022, 18:38
Juri
Периодически у меня получается, что внутри одного актора используются vi из другого актора. В итоге в скомпилированной библиотеке .lvlibp находится второй актор целиком. В ручную я это исправляю легко, но хочется автоматизировать хотябы проверку, чтобы добавить Pre-Build Action, который будет проверять, не попадаются ли vi из чужого актора. Как сделать такую проверку?

UPD: нашел решение. Потом выложу