Используя концепции, извлеченные из знаменитой Красной книги 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», пересмотреть и перекомпилировать мою сервисную программу, а затем пересмотреть и перекомпилировать все программы, которые на нее ссылаются. Я могу следовать этому решению, но есть несколько тревожных вопросов, возникающих в связи с таким поведением:
Почему функция IFS в стиле C использует собственный интерфейс Java для выполнения своей работы? Я вижу импорт служебных программ, таких как
QC2IFS
иQC2POSIX
, которые вполне понятны в контексте. Похоже, IBM ввела здесь неожиданную зависимость, с которой нам придется смириться. Я уверен, что это одна из служебных программ C, ссылающихся наQJVAJNI
, потому что, когда я комментирую вызов функцииaccess
, наQJVAJNI
не ссылаются. Возможно, ссылка на сервисную программуQJVAJNI
имеет несколько уровней глубины, что означает импорт импорта импорта.Почему связыватель так тщательно рекурсирует через импорт сервисной программы? Связыватель выглядит так, как будто он проходит через каждый импорт, который использует каждая сервисная программа, независимо от того, используется ли этот импорт программой и связываемыми подпроцедурами. Это необходимо? Не получится ли рекурсивно проверить только те импорты, которые используются на каждом уровне? Есть ли способ изменить это поведение?
Если с этими двумя вопросами ничего нельзя поделать, значит ли это, что для гарантии того, что связывание всегда будет работать (особенно для функций «общего назначения», таких как обработка ошибок), нужно убедиться, что нет никакой другой экспортируемой процедуры? где-нибудь на машине с таким же именем? Я не знаю никаких средств, таких как пространства имен, которые облегчили бы эту проблему. Насколько мне известно, компиляторы ILE не используют никаких подходов, таких как перегрузка или изменение имени, которые могли бы использоваться в этой ситуации на других платформах. Было бы хорошей практикой начать «неофициальное пространство имен», как я вижу в некоторых экспортах C (например,
_C_NEU_IFS_feof
), чтобы предотвратить конфликты имен? В качестве альтернативы, есть ли способ поиска всех экспортированных процедур на машине, чтобы найти желаемое имя перед публикацией сервисной программы?Авторы IBM Red Paper являются тяжеловесами в мире программирования ILE. Они назвали один из своих рекомендуемых экспортов «Throw», как и я (хотя и с другим списком параметров). Сталкивались ли они с подобными проблемами? Был ли у них другой способ разрешить конфликт имен?
Я обнаружил, что есть опция *DUPPROC
, которую можно указать для CRTPGM
, но я не уверен, что это хорошая идея. В документации говорится: «Если разрешено несколько повторяющихся процедур, выбирается первая экспортируемая процедура в списке указанных модулей и служебных программ, соответствующая запросу на импорт». Можете ли вы быть уверены, какой символ будет первым в списке? Порядок строго определен?