Чтение неглобальной переменной из другой программы во время выполнения

#dynamic #abap

#динамический #abap

Вопрос:

Я хотел бы получить доступ к переменной с уровня 5, когда я нахожусь на уровне 11 стека.

Оба уровня относятся к разным программам:

 lvl    type       event              program                 include 
11     METHOD     SET_PERNRS_TAB     <my_program>            <my_include>.
...
05     FORM       PUT_PERNR          <ldb_program>          <ldb_include>.
04     FORM       %_ROOT             <ldb_program>          <ldb_include>.
...
 

Вот как я сейчас это делаю:

 constants lc_ldb_pernr_tab   type string value `(LDB_PROGRAM)INDEX[]`.
field-symbols <lt_pernr_tab> type any table.

assign (lc_ldb_pernr_tab) to <lt_pernr_tab>.
 

И теперь я могу использовать <lt_pernr_tab> , которая является «копией» переменной index[] , полученной из LDB, в другой программе.

Проблема здесь в том, что она работает только с некоторыми переменными, но не с другими… пожалуйста, найдите ниже объявление двух переменных внутри программы ldb.

Я пытаюсь получить их значение из своей программы, но работает только одна.

  1. тот, который работает, index :
 DATA: BEGIN OF COMMON PART $pnp-index$.
  DATA: BEGIN OF index OCCURS 1000,
          pernr LIKE pernr-pernr,
        END OF index.
DATA: END   OF COMMON PART.
 
  1. тот, который не, index_all :
   DATA: index_all TYPE t_t_pernr.
 

Это означает, что этот процесс (program)variable работает только с переменными, которые объявлены ldb как « common part «?

Другими словами, невозможно получить содержимое index_all из программы LDB, когда я нахожусь внутри моей программы, поскольку оно не из « common part «?

-> чтобы дать небольшой контекст, index_all содержит все записи, которые мне нужны, в то время index как это просто раздел index_all . ldb выполняет итерацию index , и когда она завершена, она обновляет ее следующими индексами index_all .

Ответ №1:

Я думаю, что в документации все сказано :

Только для внутреннего использования имя в name может также иметь форму «(PROG) DOBJ», где «PROG» — это имя программы ABAP, а «DOBJ» — имя глобального объекта данных этой программы (эти имена не чувствительны к регистру). Если программа «PROG» загружается в тот же внутренний сеанс, что и текущая программа, когда выполняется оператор ASSIGN, объект данных «DOBJ» найден в этой программе, и символ поля указывает на этот объект данных, если назначение было успешным.

Обратите внимание на «только для внутреннего использования», т. Е. Эта специальная форма присваивания может быть удалена в любой будущей версии ABAP (но я сомневаюсь).

Итак, вероятно, вы хотите получить доступ к переменной, которая не является глобальной, т.Е. Либо Локальной, либо атрибутом экземпляра, либо частным / защищенным статическим атрибутом…

ASSIGN ('PROG(DOBJ)') работает с a common part , поскольку имеет глобальную область видимости. Обратите внимание, что общая часть также может использоваться без присвоения другими программами, которые принадлежат к той же «группе» (1), путем объявления того же имени «общей части».

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

Если вы не можете адаптировать программу (потому что она стандартная), существует следующий обходной путь для доступа к локальному объекту данных.

Допустим, эта программа «PROG» и содержит процедуру «X», которая содержит локальный объект данных «LOCVAR», который вы хотите прочитать. Для этого вы можете использовать Enhancement Framework. Итак, чтобы сделать ее доступной из внешних программ:

  • В PROG объявите глобальную переменную ссылки на данные (2), скажем DATA ZZ_REF_LOCVAR TYPE REF TO DATA (рекомендация: префикс «ZZ», чтобы ограничить конфликты с будущими исправлениями программы)
  • В начале процедуры «X» инициализируйте ZZ_REF_LOCVAR кодом ASSIGN ('LOCVAR') TO FIELD-SYMBOL(<zz_locvar>). zz_ref = ref #( <zz_locvar> ). (3)
  • В вашей собственной программе, если процедура «X» в настоящее время находится в стеке вызовов, которую вы можете проверить с помощью класса CL_ABAP_GET_CALL_STACK , теперь вы можете получить доступ к глобальной ссылке на данные, которая указывает на локальную переменную с помощью этого кода: FIELD-SYMBOLS <ref_locvar> TYPE REF TO DATA. FIELD-SYMBOLS <locvar>. ASSIGN ('(PROG)ZZ_REF_LOCVAR') TO <ref_locvar>. ASSIGN <ref_locvar>->* TO <locvar> .
  • Небольшой вариант этого решения — объявить ZZ_REF_LOCVAR как статический общедоступный атрибут в пользовательском пуле классов и получить к нему доступ как из стандартной программы, так и из вашего собственного кода.

Будьте осторожны, это может больше не работать, если будущий патч удалит локальную переменную. В любом случае, это замечание справедливо и для глобальных переменных.


(1) Примечание: «группа» программ формируется из программ, вызываемых через PERFORM IN PROGRAM или CALL SUBSCREEN с помощью PROG, и у них есть общая область памяти, называемая «рабочая область интерфейса«.

(2) Примечание: я предлагаю глобальную переменную ссылки на данные, а не глобальный символ поля, поскольку символы полей не могут быть объявлены глобально в таких программах, как пулы классов.

(3) Примечание: неявное улучшение в начале процедуры «X» не может получить доступ к локальным переменным напрямую, присвоив им имена, поскольку они DATA находятся после улучшения; обходным путем является использование символа поля для доступа к локальной переменной во время выполнения.

Комментарии:

1. ваше предложение кажется правильным, спасибо, Сандра! Хотя для добавления глобальной ссылки требуются изменения в программе, которая не является моей, похоже, что другого способа нет. возможно, я попрошу ребят, которые поддерживают программу, добавить дополнительную ссылку: D еще раз, спасибо!

2. Если другая программа является пользовательской, просто попросите своего коллегу-разработчика адаптировать ее, чтобы сделать данные доступными извне. Решение, предложенное выше, является худшим из всех!