Как избежать неожиданных конфликтов имен процедур в сервисных программах?

Используя концепции, извлеченные из знаменитой Красной книги IBM по обработке исключений и ошибок RPG, я написал сервисная программа QGPL/ERRFUNC для реализации повторно используемых функций ошибок, таких как Assert, Throw, ThrowMsg, Rethrow и GetErrorMsg. Я использовал их в нескольких разных программах, и они работали хорошо.

Только что я использовал функцию Throw в программе RPG ILE, которая также статически вызывает функцию access в стиле C, которая используется с потоковыми файлами в файловой системе IFS. Эта программа не будет компилироваться с ошибкой привязки «Определение предоставлено несколько раз для символа Throw». Насколько мне известно, при компиляции с помощью команды CRTBNDRPG невозможно получить сведения о привязке, но я смог закомментировать свою спецификацию H DFTACTGRP(*NO), а затем скомпилировать ее, используя CRTRPGMOD, за которой следует CRTPGM с дополнительным параметром DETAIL(*EXTENDED). Это распечатывает обширный список всех имен процедур, на которые обращает внимание компилятор при определении того, с какими процедурами следует выполнять статическую привязку. Это выявило двойное определение «Бросок». Глубоко внутри 72-страничного листинга упоминалась предоставленная IBM сервисная программа QJVAJNI (Java Native Interface), которая содержит экспортированную процедуру, также называемую «Throw».

Теперь самым простым решением моей непосредственной проблемы было бы просто переименовать мою процедуру «Throw», пересмотреть и перекомпилировать мою сервисную программу, а затем пересмотреть и перекомпилировать все программы, которые на нее ссылаются. Я могу следовать этому решению, но есть несколько тревожных вопросов, возникающих в связи с таким поведением:

  1. Почему функция IFS в стиле C использует собственный интерфейс Java для выполнения своей работы? Я вижу импорт служебных программ, таких как QC2IFS и QC2POSIX, которые вполне понятны в контексте. Похоже, IBM ввела здесь неожиданную зависимость, с которой нам придется смириться. Я уверен, что это одна из служебных программ C, ссылающихся на QJVAJNI, потому что, когда я комментирую вызов функции access, на QJVAJNI не ссылаются. Возможно, ссылка на сервисную программу QJVAJNI имеет несколько уровней глубины, что означает импорт импорта импорта.

  2. Почему связыватель так тщательно рекурсирует через импорт сервисной программы? Связыватель выглядит так, как будто он проходит через каждый импорт, который использует каждая сервисная программа, независимо от того, используется ли этот импорт программой и связываемыми подпроцедурами. Это необходимо? Не получится ли рекурсивно проверить только те импорты, которые используются на каждом уровне? Есть ли способ изменить это поведение?

  3. Если с этими двумя вопросами ничего нельзя поделать, значит ли это, что для гарантии того, что связывание всегда будет работать (особенно для функций «общего назначения», таких как обработка ошибок), нужно убедиться, что нет никакой другой экспортируемой процедуры? где-нибудь на машине с таким же именем? Я не знаю никаких средств, таких как пространства имен, которые облегчили бы эту проблему. Насколько мне известно, компиляторы ILE не используют никаких подходов, таких как перегрузка или изменение имени, которые могли бы использоваться в этой ситуации на других платформах. Было бы хорошей практикой начать «неофициальное пространство имен», как я вижу в некоторых экспортах C (например, _C_NEU_IFS_feof), чтобы предотвратить конфликты имен? В качестве альтернативы, есть ли способ поиска всех экспортированных процедур на машине, чтобы найти желаемое имя перед публикацией сервисной программы?

  4. Авторы IBM Red Paper являются тяжеловесами в мире программирования ILE. Они назвали один из своих рекомендуемых экспортов «Throw», как и я (хотя и с другим списком параметров). Сталкивались ли они с подобными проблемами? Был ли у них другой способ разрешить конфликт имен?

Я обнаружил, что есть опция *DUPPROC, которую можно указать для CRTPGM, но я не уверен, что это хорошая идея. В документации говорится: «Если разрешено несколько повторяющихся процедур, выбирается первая экспортируемая процедура в списке указанных модулей и служебных программ, соответствующая запросу на импорт». Можете ли вы быть уверены, какой символ будет первым в списке? Порядок строго определен?


person Mike    schedule 07.02.2018    source источник


Ответы (1)


В RPG или C, если на то пошло, нет пространства имен. Когда вы связываете программы ILE, каталог связывания определяет, какие служебные программы (и модули) используются для разрешения имен. Это не каждая сервисная программа в системе. Но есть также некоторые служебные программы, которые привязаны по умолчанию, и если вы используете имя, которое экспортируется одной из этих автоматически связываемых служебных программ, у вас возникнут проблемы с повторяющимися именами. Вы правы, *DUPPROC — плохая идея. Единственный способ справиться с именами, дублирующими процедуры в автоматически связываемых сервисных программах, — это не определять новые процедуры с такими именами. Некоторые люди используют методы псевдопространства имен, такие как serviceprogramname_procedurename или applicationprefix_procedurename, при именовании своих процедур. Другие просто удостоверяются, что их процедуры имеют уникальные имена другими способами. Но пока RPG не поддерживает какое-либо пространство имен, вам придется использовать какую-то произвольную схему именования, чтобы обеспечить уникальность имен процедур.

Кстати, на developerworks есть RFE для добавления пространств имен в RPG. . Чтобы ссылка работала, вам необходимо войти в систему на сайте developerworks, но вы можете зарегистрироваться бесплатно. Тогда посетите RFE и проголосуйте за него.

person jmarkmurphy    schedule 08.02.2018
comment
Я абсолютно согласен. На данный момент использование псевдопространства имен — единственный выход. - person Mihael; 09.02.2018