Генерация исключений в CODESYS

Как я могу генерировать стандартные системные исключения (и, если возможно, создавать собственные исключения и также генерировать их).

Самое простое, что приходит на ум, это просто разделить переменную на ноль, но это в лучшем случае просто хак.

Я нашел упоминания о функции AppGenerateException в библиотеке CmpApp, но не могу найти для нее ни документации, ни примеров. Может ли кто-нибудь указать мне на какую-то документацию для этого?


person Guiorgy    schedule 02.06.2020    source источник
comment
Можете ли вы рассказать немного больше, чего вы пытаетесь достичь? Возможно, есть совсем другой подход к решению вашей задачи.   -  person Sergey Romanov    schedule 03.06.2020
comment
@Сергей Романов, как я уже сказал, в CODESYS у нас есть __TRY, __CATCH и __FINALLY для перехвата EXCEPTION, выдаваемых стандартными функциями. Как я могу сделать то же самое. И если возможно, могу ли я определить пользовательские исключения и использовать их?   -  person Guiorgy    schedule 03.06.2020
comment
Try, catch и т. д. в codesys предназначены для обнаружения системных исключений, таких как деление на ноль и т. д. Я согласен с Сергеем, есть миллион других способов добиться этого, возможно, лучшим способом.   -  person Quirzo    schedule 04.06.2020
comment
Я добавил один ответ. Но я все же считаю, что Сергей прав.   -  person Quirzo    schedule 04.06.2020
comment
@Quirzo, я не буду отрицать, что может быть лучший способ, однако я родом из ООП (объектно-ориентированного программирования), такого как C #, JAVA и KOTLIN, где создание и обработка исключений является основной механикой, на мой взгляд. Кроме того, я просто хочу знать, возможно ли это, и использовать это или нет, а что лучше - это субъективное предпочтение.   -  person Guiorgy    schedule 04.06.2020
comment
@Guiorgy абсолютно неправильно пытаться применять стили шаблонов программирования и подходы C-подобного языка к ST. Это похоже на то, как если бы вы дали мне бутылку, и я бы спросил, где ручка, и аргументирую это, потому что я исхожу из опыта использования чашки. В разных языках разные задачи решаются по-разному. Как я уже сказал, скажите, что вы хотите сделать, и, возможно, есть элегантный способ сделать это, а не пытаться объединить технику, которая никогда не предназначалась для этого языка.   -  person Sergey Romanov    schedule 04.06.2020
comment
@Serget Romanow, в IEC 61131 добавляется все больше и больше элементов ООП, так что ясно, что это направление, в котором все движется. Однако, как я уже сказал, я согласен с тем, что могут быть лучшие решения, но что выбрать, остается на усмотрение отдельных (и команды, других, кроме меня, таких как ООП) предпочтений. Я хотел знать, как решить мою проблему с помощью этого метода, если это вообще возможно. Что касается того, почему я этого хотел, пожалуйста, прочитайте мой комментарий к ответу Quirzo, и если вы считаете, что есть лучший подход к проблеме, обязательно скажите, я новичок в программировании ПЛК и ценю любую помощь! ;)   -  person Guiorgy    schedule 04.06.2020


Ответы (1)


Из любопытства я проверил AppGenerateException и все заработало. Получил помощь на этой справочной странице Codesys.

Я все еще думаю, что это не лучший способ добиться того, что вам нужно, но он может сработать.

К сожалению, у меня 64-битная система, а TRY..CATCH пока не работает в других 32-битных системах, насколько мне известно, поэтому я не смог проверить отлов.

Добавьте следующие библиотеки:

  • CmpApp
  • SysExcept

Тогда следующий код работает. Установите для ThrowErr значение true, чтобы получить системное исключение.

PROGRAM PRG_TestThrow
VAR CONSTANT
    MY_PRIVATE_EXCEPTION : DWORD := 32001;
END_VAR
VAR
    ThrowErr    : BOOL; //Set this to TRUE to throw an error

    //The next two are for getting App instance
    _pApp       : POINTER TO CmpApp.APPLICATION;
    _Result     : SysExcept.SysTypes.RTS_IEC_RESULT;
END_VAR



//Get App instance
_pApp := AppGetCurrent(pResult := ADR(_Result));

IF ThrowErr THEN
    ThrowErr := FALSE;

    IF _pApp <> 0 THEN
        //Throw divide by zero exception
        AppGenerateException(pApp:=_pApp,   ulException:=RtsExceptions.RTSEXCPT_DIVIDEBYZERO);

        //You could use probably any available number as your own custom exception. 
        //For example the following works BUT not sure if it's ok to this.
        //AppGenerateException(pApp:=_pApp,   ulException:=MY_PRIVATE_EXCEPTION);

        //See RtsExceptions type for available exception codes. 
        //For my Codesys version, it has largest exception number of 0x2000 so all larger number are free (for now...)
    END_IF
END_IF

Кажется, что можно использовать любой пользовательский код исключения, например:

AppGenerateException(pApp:=_pApp,   ulException:=MY_PRIVATE_EXCEPTION);

Но это не задокументировано, поэтому я был бы осторожен.

person Quirzo    schedule 04.06.2020
comment
@Quizon, спасибо за ответ, я попробую в ближайшее время, когда смогу. Просто чтобы быть уверенным, что try catch не работает с x64, это где-нибудь задокументировано? Также, если вы не возражаете, когда вы говорите, что есть лучшие способы, не могли бы вы дать мне несколько предложений? Не нужно углубляться, просто некоторые ссылки для дальнейшего чтения также будут оценены! - person Guiorgy; 04.06.2020
comment
И добавить: я бы использовал методы, выходные данные или свойства функциональных блоков, таких как IsError, GetError, для получения информации об ошибках. Выходы ошибок функционального блока довольно часто используются при кодировании ПЛК, поэтому другие программисты сразу узнают, что происходит. Но если вы хотите использовать TRY..CATCH, я бы создал функцию наподобие Throw, которая творит чудеса и использует ваши собственные коды ошибок, определенные где-то. - person Quirzo; 04.06.2020
comment
спасибо за отличный ответ. Я не собираюсь использовать исключения для времени выполнения (по крайней мере, на данный момент), мой основной сценарий таков: предположим, у меня есть функция, которая принимает ENUMERATOR в качестве входных данных, но в этом случае я принимаю только часть его значений как действительные . Я хочу, чтобы кто-то, использующий мою функцию, никогда не передал такое значение, создав исключение, которое остановит их выполнение и отобразит ошибку в журналах. В идеале я хотел бы передать сообщение с исключением/ошибкой, но не уверен, что это возможно? Считаете ли вы создание исключения хорошим решением в таком случае? - person Guiorgy; 04.06.2020
comment
Если вы используете его сами или если вы очень документируете его, все может быть в порядке. Но подумайте о сценарии, когда кто-то использует ваш блок, но не знает об этом. Машина работает, и ПЛК передает в этот блок неверное значение, после чего выдается исключение. Но пользователь не знал об исключениях, поэтому нет попытки .. поймать, и ПЛК остановится так же, как и машина. Это может быть совсем плохая ситуация. Возможно, лучшим решением было бы что-то вроде именованного вывода valid, которое будет верным, если расчет в порядке и можно использовать возвращаемое значение? - person Quirzo; 10.06.2020
comment
интересное предложение. У меня есть все намерения полностью задокументировать мой код, но я думаю, что представлю два варианта другим и решу с ними лучший выбор для нас. В любом случае, спасибо за ваше время! - person Guiorgy; 11.06.2020