다음을 통해 공유


X++의 매크로

비고

커뮤니티 관심 그룹은 이제 Yammer에서 Microsoft Viva Engage로 이동했습니다. Viva Engage 커뮤니티에 가입하고 최신 토론에 참여하려면 Finance and Operations Viva Engage Community 양식에 대한 요청 액세스 권한을 작성하고 참여하려는 커뮤니티를 선택합니다.

이 문서에서는 X++에서 매크로를 만들고 사용하는 방법을 설명합니다.

미리 컴파일러 지시문, 즉 매크로는 코드를 컴파일하기 전에 개념적으로 처리됩니다. 지시문은 매크로와 해당 값을 선언하고 처리합니다. 지시문은 지정한 콘텐츠로 바뀝니다. 따라서 컴파일러에서 해당 지시문이 발생하지 않습니다. X++ 컴파일러는 지시문에 의해 X++ 코드에 기록된 문자 시퀀스만 볼 수 있습니다.

경고

매크로는 레거시 기능이며 향후 릴리스에서는 더 이상 사용되지 않을 수 있습니다. 대신 언어 구문을 사용합니다. 매크로 대신 다음과 같은 언어 구문을 사용합니다.

매크로 정의

아래와 같은 구문을 사용하여 명명된 매크로를 정의합니다.

  • #define. MyMacro(Value)는 선택적 값으로 매크로를 만듭니다.
  • #if. MyMacro는 매크로가 정의되어 있는지 확인합니다.
  • #undef. MyMacro는 매크로 정의를 제거합니다.

#define 및 #if 지시문

모든 미리 컴파일러 지시문 및 기호는 문자로 # 시작합니다.

다음 구문을 사용하여 매크로를 정의합니다.

#define.MyMacro(Value) // creates a macro with a value.
#define.AnotherMacro() // creates a macro without a value.

코드의 아무 곳이나 매크로를 정의할 수 있습니다. 매크로는 문자 시퀀스인 값을 가질 수 있지만 값을 가질 필요는 없습니다. 지시문은 #define 선택적으로 값을 포함하여 매크로 변수를 만들도록 미리 컴파일러에 지시합니다.

지시문은 #if 다음 예제와 같이 변수가 정의되었는지 여부와 선택적으로 특정 값이 있는지 여부를 확인합니다.

#if.MyMacro
  // The MyNaacro is defined.
#endif

#ifnot.MyMacro
  // The MyNaacro is not defined.
#endif

X++ 미리 컴파일러 지시문, 정의한 매크로 이름 및 #if 지시문 값 테스트는 모두 대/소문자를 구분하지 않습니다. 그러나 대문자로 시작하는 매크로 이름을 정의합니다.

#undef 지시문

지시문을 #undef 사용하여 이전 #define의 매크로 정의를 제거합니다.

#undef.MyMacro
#if.MyMacro
   // The macro is not defined, so this is not included
#endif

다른 #undef매크로 이름을 사용하여 제거한 #define 매크로 이름을 다시 정의할 수 있습니다.

매크로 값 사용

매크로 이름을 정의하여 값을 가질 수 있습니다.

#define.Offset(42)
...
print #Offset; // 42

매크로 값에는 특정 데이터 형식이 없으며 문자 시퀀스일 뿐입니다. 지시문 끝에 #define.MyMacro 괄호로 묶인 값을 제공하여 매크로에 값을 할당합니다. X++ 코드에서 값이 발생하도록 하려면 매크로 기호를 사용합니다. 매크로 기호는 접두사로 추가된 문자가 # 있는 매크로의 이름입니다. 다음 코드 샘플에서는 매크로 기호 #MyMacro 보여줍니다 . 기호가 매크로 값으로 대체됩니다.

매크로 값 테스트

매크로를 테스트하여 값이 있는지 여부를 확인할 수 있습니다. 값이 특정 문자 시퀀스인지 여부를 확인할 수도 있습니다. 이러한 테스트를 통해 X++ 프로그램에 코드 줄을 조건부로 포함할 수 있습니다. 정의된 매크로에 값이 있는지 여부를 테스트할 수 있는 방법은 없습니다. 매크로 값이 특정 값과 일치하는지 여부만 테스트할 수 있습니다. 가장 좋은 방법은 정의한 매크로 이름에 대한 값을 항상 정의하거나 값을 정의하지 않는 것입니다. 이러한 모드를 번갈아 사용하면 코드를 이해하기가 어려워집니다.

#defInc 및 #defDec 지시문

#defInc #defDec 매크로 값을 해석하는 유일한 지시문입니다. 미리 컴파일러가 정식 int 형식으로 변환할 수 있는 값이 있는 매크로에만 적용됩니다. 이러한 지시문은 컴파일 시간에 매크로의 숫자 값을 변경합니다. 값은 숫자만 포함할 수 있습니다. 허용되는 숫자가 아닌 문자는 선행 음수 기호(-)입니다. 정수 값은 int64가 아닌 X++ int로 처리됩니다. 지시문에서 #defInc 사용하는 매크로 이름의 경우 매크로를 #define 만드는 지시문은 클래스 선언에 있으면 안 됩니다. 이러한 경우의 #defInc 동작은 예측할 수 없습니다. 대신 메서드에서만 이러한 매크로를 정의합니다. 정수 값이 #defInc 있는 매크로에 대해서만 and #defDec 지시문을 사용합니다. 미리 컴파일러는 매크로 값이 정수가 아니거나 값이 비정상적이거나 극단적인 경우에 대한 #defInc 특수 규칙을 따릅니다. 다음 표에서는 0으로 변환한 다음 증분하는 값을 #defInc 나열합니다. 값을 0으로 변환하는 경우 #defInc#defDec.

매크로 값 defInc 값 행동
(+55) 56 양수 기호(+) 접두사를 사용하면 미리 컴파일러가 이 값을 숫자가 아닌 문자열로 처리합니다. 미리 컴파일러는 (또는#defInc) 지시문을 처리할 때 숫자가 아닌 모든 문자열을 #defDec 0으로 처리합니다.
("3") 1 따옴표로 묶인 정수는 0으로 처리됩니다.
( ) 1 공백 문자열은 0으로 처리됩니다.
() 1 길이가 0인 문자열은 0으로 처리됩니다.
(임의 문자열) 1 숫자가 아닌 문자 문자열은 0으로 처리됩니다.
(0x12) 1 16진수는 숫자가 아닌 문자열로 처리됩니다. 따라서 미리 컴파일러는 0으로 변환합니다.
(-44) -43 음수는 허용됩니다.
(2147483647) -2147483648 최대 양의 int 값은 최소 음수 int 값으로 #defInc오버플로됩니다.
(999888777666555) 1 int 및int64의 용량을 초과하는 많은 수입니다.
(5.8) 1 실수는 0으로 해석됩니다.
1 지시문 #define.MyValuelessMacro 에 값이 없고 괄호가 제공되지 않으면 값은 0입니다.

#globaldefine 지시문

지시 #globaldefine 문은 지시문과 #define 비슷합니다. #define대신 #globaldefine 사용합니다.

#localmacro 및 #macro 지시문

#localmacro 이 지시문은 매크로에 여러 줄 길이의 값을 포함하거나 매크로 값에 닫는 괄호가 포함되어 소스 코드 조각을 포함할 수 있는 좋은 후보인 경우에 적합합니다.

    #macro.RetailMatchedAggregatedSalesLine(
                %1.price            == %2.price
        &&      %1.businessDate     == %2.businessDate
        &&      %1.itemId           == %2.itemId
        &&      ((((%3) && (%1.qty <= 0)) || ((! %3) && (%1.qty > 0))) || (%4))
    )
    #endmacro

지시문은 #localmacro 로 작성 #macro할 수 있습니다. 그러나 #localmacro 권장되는 용어입니다. 지시문을 #if 사용하여 매크로 이름이 지시문과 함께 선언되었는지 여부를 테스트할 #define 수 있습니다. 그러나 매크로 이름이 지시문으로 선언되었는지 여부를 테스트할 #localmacro 수는 없습니다. 지시문을 사용하여 #define 선언된 매크로만 지시문의 영향을 받습니다 #undef . #define 지시문에서 이미 범위에 있는 이름을 .로 #localmacro지정할 수 있습니다. 매크로를 삭제 #localmacro 하고 만드는 #define 효과가 있습니다. 이는 반대 시퀀스에도 적용됩니다. 즉, a가 #localmacro 다시 정의할 수 있습니다 #define. 매크로 이름과 값이 모두 있는 A #localmacro 는 항상 이름이 같은 이전 #localmacro 을 재정의합니다. 이 같은 문제가 발생합니다.#globaldefine 매크로와 #define 매크로의 #localmacro 주요 차이점은 구문이 종료되는 방식입니다. 종결자는 다음과 같습니다.

  • #define – 에 의해 종료됩니다. )
  • #localmacro – 에 의해 종료됩니다. #endmacro

#localmacro 는 여러 줄 값이 있는 매크로에 더 적합합니다. 여러 줄 값은 일반적으로 X++ 또는 SQL 코드 줄입니다. X++ 및 SQL에는 많은 괄호가 포함되어 있으므로 #define 조기에 종료됩니다. #define 둘 다 #localmacro 단일 줄 또는 후속 줄에서 선언 및 종료할 수 있습니다. 실제로 선언 #define 된 것과 동일한 줄에서 종료됩니다. 실제로 #localmacro 후속 줄에서 종료됩니다.

매크로 매개 변수

매개 변수 기호를 포함하도록 매크로 값을 정의할 수 있습니다. 첫 번째 매개 변수 기호는 %1, 두 번째는 등입니다 %2. 확장에 대한 매크로 기호 이름을 참조할 때 매개 변수에 대한 값을 전달합니다. 매크로 매개 변수 값은 형식 형식이 없는 문자 시퀀스이며 쉼표로 구분됩니다. 매개 변수 값의 일부로 쉼표로 전달할 수 있는 방법은 없습니다. 전달된 매개 변수 수는 매크로 값이 수신하도록 설계된 매개 변수 수보다 작거나, 크거나, 같을 수 있습니다. 시스템은 전달된 매개 변수 수의 불일치를 허용합니다. 매크로가 예상한 것보다 적은 수의 매개 변수가 전달되는 경우 생략된 각 매개 변수는 길이가 0인 문자 시퀀스로 처리됩니다.

매크로 기호 중첩

외부 정의 지시문 내에 미리 컴파일러 정의 지시문을 중첩할 수 있습니다. 기본 정의 지시문은 다음과 #define같습니다#localmacro.

지시문은 #define 지시문 내에 #localmacro 제공될 수 있으며, 지시문은 #localmacro .에 #define속할 수 있습니다.

#macrolib 지시문

코드 노드 아래의 매크로 노드 아래에 있는 애플리케이션 탐색기에는 매크로 지시문 집합을 포함하는 많은 라이브러리 노드가 있습니다. #define 둘 다 #localmacro 이러한 매크로 라이브러리의 내용에 자주 나타납니다. #macrolib 사용할 수 있습니다 . X ++ 코드에 매크로 라이브러리의 내용을 포함하기 위한 MyAOTMacroLibrary입니다. 및 #if 지시문은 #undef 이름에 #macrolib 적용되지 않습니다. 그러나 매크로의 #define 내용인 지시문에는 적용 #macrolib 됩니다. 지시문 #macrolib. MyAOTMacroLibrary 는 #MyAOTMacroLibrary 작성할 수도 있습니다 .#macrolib 접두사는 나중에 코드를 읽는 사람에게 모호하지 않으므로 권장됩니다.

#linenumber 지시문

코드를 개발 및 디버깅하는 동안 지시문을 사용할 #linenumber 수 있습니다. 매크로가 확장되기 전에 코드 파일의 실제 줄 번호로 대체됩니다.

매크로 범위

매크로를 참조할 수 있는 범위는 매크로를 정의하는 위치에 따라 달라집니다. 클래스에서 부모 클래스에서 정의한 매크로를 참조할 수 있습니다. 미리 컴파일러가 자식 클래스를 처리할 때 먼저 상속 체인을 루트 클래스로 추적합니다. 그런 다음, 미리 컴파일러는 루트 클래스에서 컴파일되는 클래스로 모든 지시문을 처리합니다. 모든 매크로와 해당 값을 내부 테이블에 저장합니다. 각 클래스 선언의 지시문 결과는 상속 체인의 앞부분에서 찾은 지시문에서 이미 채워진 내부 테이블에 적용됩니다.

그러나 미리 컴파일러는 각 메서드를 개별적으로 처리합니다. 현재 메서드를 처리하기 전과 마찬가지로 테이블의 상태를 복원할 수 있도록 내부 테이블을 업데이트합니다. 사전 컴파일러는 첫 번째 메서드를 처리한 후 다음 메서드를 처리하기 전에 내부 테이블을 복원합니다.

이 컨텍스트에서 메서드는 AOT(애플리케이션 개체 트리)에서 메서드 노드의 내용으로 정의됩니다. AOT에서 클래스 노드를 확장하고 클래스 노드를 확장하고 메서드 노드를 마우스 오른쪽 단추로 클릭한 다음 편집을 선택할 수 있습니다. 그런 다음 메서드 선언 앞에 줄을 #define.MyMacro("abc") 추가할 수 있습니다. 미리 컴파일러는 메서드 블록 외부에서 #define 발생하더라도 #define{} 지시문을 메서드의 일부로 처리합니다.