DelphiScript
이 섹션에서는 Altium Designer Scripting Engine에서 사용하는 DelphiScript 언어를 설명하고, 지원되는 문장(statement), 함수(function), 확장(extension)에 대한 참조 정보를 제공합니다. 이는 Altium Designer를 직접 제어하고 통신하는 데 사용되는 특수 프로시저입니다.
이 참조에 포함된 내용:
- DelphiScript와 Delphi의 차이점
- DelphiScript 키워드
- DelphiScript 문장 및 연산자
- DelphiScript 함수
- DelphiScript 폼 및 컴포넌트
DelphiScript 언어
이 DelphiScript 참조는 기본적인 프로그래밍 개념과 Altium Designer의 기본 동작에 익숙하다는 것을 전제로 합니다. 스크립팅 시스템은 Embarcadero Delphi™와 매우 유사한 DelphiScript 언어를 지원합니다.
핵심적인 차이점은 DelphiScript가 무타입(typeless) 또는 비정형(untyped) 스크립팅 언어라는 점입니다. 즉, 레코드나 클래스를 정의할 수 없고, 포인터를 함수의 매개변수로 전달할 수도 없습니다. 다만 가독성을 위해 스크립트 내에서 변수 선언은 여전히 가능합니다.
이 페이지와 함께 제공되는 하위 페이지에는 DelphiScript 스크립팅 언어를 구성하는 인터페이스, 컴포넌트, 전역 루틴, 타입, 변수에 대한 참조 자료가 포함되어 있습니다.
DelphiScript 핵심 요소
객체(Objects)
DelphiScript에서 객체(Object)는 메서드로 구성되며, 많은 경우 속성(Properties)과 이벤트(Events)도 포함합니다. 속성은 객체에 포함된 데이터를 나타내고, 메서드는 객체가 수행할 수 있는 동작이며, 이벤트는 객체가 반응할 수 있는 조건입니다. 모든 객체는 TObject 타입의 최상위 객체로부터 파생(상속)됩니다.
객체 인터페이스(Object Interfaces)
객체 인터페이스(Object Interface)는 메서드로 구성되며, 많은 경우 속성도 포함하지만 데이터 필드(data field)는 가질 수 없습니다. 인터페이스는 기존 객체를 나타내며, 각 인터페이스에는 고유성을 나타내는 GUID가 있습니다. 속성은 인터페이스가 연결된 객체에 포함된 데이터를 나타냅니다. 메서드는 (인터페이스가 연결된) 객체가 수행할 수 있는 동작입니다.
컴포넌트(Components)
컴포넌트는 Tool Palette 패널의 시각적 객체로, 설계 시점(design time)에 조작할 수 있습니다. 모든 컴포넌트는 Embarcadero Delphi Visual Component Library(VCL)의 TComponent 시스템 클래스에서 파생됩니다.
루틴(Routines)
전역 루틴(Global Routine)은 스크립팅 시스템의 프로시저(Procedure)와 함수(Function)입니다. 이러한 루틴은 클래스의 일부가 아니지만, 스크립트에서 직접 호출하거나 클래스 메서드 내부에서 호출할 수 있습니다.
타입(Types)
변수 타입(Variable Type)은 인터페이스 메서드 및 속성, 객체 메서드/속성/이벤트, 전역 루틴의 반환 타입(Return type)과 매개변수 타입(Parameter type)으로 사용됩니다. 많은 경우 타입은 API 문서의 열거형 타입(Enumerated Types) 섹션에 문서화되어 있습니다.
Altium Designer와 Delphi RTL
스크립팅 시스템은 Embarcadero Delphi Run Time Library(RTL)의 일부(subset)와 Altium Designer API를 지원합니다.
DelphiScript 소스 파일
Altium Designer에서 스크립트 프로젝트는 스크립트 문서(스크립트 Unit 및 스크립트 Form)를 저장하도록 구성됩니다. 스크립트는 메뉴 항목, 툴바 버튼 또는 Altium Designer 메인 메뉴에서 사용할 수 있는 Select Item To Run dialog에서 실행할 수 있습니다.
PRJSCR, PAS, DFM 파일
스크립트는 *.PRJSCR 확장자를 가진 프로젝트로 구성됩니다. 각 프로젝트는 *.pas 확장자를 가진 파일들로 이루어집니다. 파일은 스크립트 Unit 또는 스크립트 Form일 수 있습니다. 각 Form에는 *.pas 확장자의 스크립트 파일과, 이에 대응하는 *.dfm 확장자의 Form 파일이 있다는 점에 유의하십시오. 스크립트 Form은 Altium Designer 위에서 실행되는 그래픽 창(대화상자)으로, 사용자가 접근 가능한 다양한 컨트롤을 호스팅합니다.
스크립트를 서로 다른 프로젝트에 첨부하는 것도 가능하며, 스크립트 수와 프로시저/함수 관리를 위해 스크립트를 여러 프로젝트로 나누어 구성하는 것을 강력히 권장합니다.
예제 스크립트
스크립트 예제 모음은 Altium Designer에서 사용할 수 있는 간단한 스크립트를 통해 DelphiScript 프로그래밍의 기본 기능을 보여줍니다.
하십시오.
아래에는 일부 예제 스크립트의 위치와 목적이 나열되어 있습니다:
Scripts\DelphiScript Scripts\DXPfolder - Client 및 system API를 시연Scripts\DelphiScript Scripts\PCB folder - PCB API를 시연Scripts\DelphiScript Scripts\Processesfolder - 서버 프로세스(Processes)를 시연Scripts\DelphiScript Scripts\Generalfolder - DelphiScript 키워드를 시연Scripts\DelphiScript Scripts\Schfolder - Schematic API를 시연Scripts\DelphiScript Scripts\WSMfolder - Workspace Manager API를 시연
DelphiScript 스크립트 작성하기
DelphiScript 명명 규칙
일반적으로 프로시저, 함수, 변수, 상수에 부여하는 이름에는 제한이 없지만, 다음 규칙을 준수해야 합니다:
- 이름에는 A~Z, a~z 문자, 밑줄 "_" 문자, 숫자 0~9를 포함할 수 있습니다.
- 이름은 문자로 시작해야 합니다.
- 이름은 DelphiScript 키워드, 지시어(directive), 예약어(reserved word)일 수 없습니다.
- 이름은 해석 시 대소문자를 구분하지 않습니다. 함수/서브루틴/변수/상수 이름을 지정할 때 대문자와 소문자를 모두 사용할 수 있지만, 인터프리터는 대소문자를 구분하지 않습니다. 대소문자만 다른 동일한 이름은 DelphiScript에서 같은 이름으로 취급됩니다.
DelphiScript 파일에서 함수와 프로시저는 Procedure-Begin-End 또는 Function-Begin-End 블록을 사용해 선언합니다. 이 두 문장 블록 모두 프로시저 또는 함수에 이름을 지정해야 합니다. DelphiScript에서는 현재 스크립트에서 사용하는 값을 보관하기 위해 이름이 있는 변수와 상수를 만들 수 있습니다.
주석 포함하기
스크립트에서 주석은 프로그래머를 위해 포함되는 실행되지 않는 코드 줄입니다. 주석은 스크립트의 거의 모든 위치에 포함할 수 있습니다.
// 뒤에 오는 모든 텍스트 또는 (* *) 또는 {}로 둘러싸인 텍스트는 DelphiScript에서 무시됩니다.
//This whole line is a comment
{This whole line is a comment}
{
These lines are comments
These lines are comments
}
(* This whole line is a comment *)
(*
These lines are comments
These lines are comments
*)
주석은 실행 코드와 같은 줄에도 포함할 수 있습니다. 예를 들어 다음 코드 줄에서 세미콜론 뒤의 모든 내용은 주석으로 처리됩니다.
ShowMessage ('Hello World'); //Display Message
로컬 변수와 전역 변수
모든 스크립트에는 로컬 변수와 전역 변수가 있으므로, 스크립트 프로젝트 내 스크립트들에서 변수 이름을 고유하게 유지하는 것이 매우 중요합니다. 변수가 outside 어떤 프로시저나 함수보다 앞에 정의되어 있으면 전역 변수이며, 같은 프로젝트의 어떤 스크립트 유닛에서도 접근할 수 있습니다.
변수가 inside 프로시저 또는 함수 내부에 정의되어 있으면, 이러한 로컬 변수는 해당 프로시저/함수 밖에서는 접근할 수 없습니다.
Example of Local and Global Variables in a Script:
// Note: The Uses keyword is not needed.
{ The global variable from UnitA script (see below) is available to this Script Unit,
as long UnitA is in the same project as this Script Unit. }
Const
GlobalVariableFromThisUnit='Global Variable from this unit';
Procedure TestLocal;
var
Local;
Begin
Local := 'Local Variable';
ShowMessage(Local);
End;
Procedure TestGlobal;
Begin
//ShowMessage(Local); // This line produces an error because the 'Local' variable is not global.
ShowMessage(GlobalVariableFromThisUnit);
// A variable from UnitA can be accessed without the Uses keyword.
ShowMessage(GlobalVariableFromUnitA);
End;
UnitA script:
Const
GlobalVariableFromUnitA = 'Global Variable from Unit A';
이름 있는 변수 사용하기
스크립트에서는 프로그램 실행 중 사용할 값을 저장하기 위해 이름 있는 변수 또는 상수를 생성합니다. 스크립트의 모든 변수는 항상 Variant 타입입니다. 타입 캐스팅은 적용되지 않으므로 변수 선언에서 타입은 무시되며 생략할 수 있습니다. 따라서 다음 선언은 올바릅니다:
Var a : integer;
Var b : integer;
Var c, d;
줄 나누기
각 코드 문장은 문장의 끝을 나타내기 위해 세미콜론 ; 문자로 종료됩니다. DelphiScript에서는 긴 명령을 두 줄 이상으로 나누어 여러 줄에 걸쳐 문장을 작성할 수 있습니다. 문장을 여러 줄로 나눌 때의 유일한 제한은 문자열 리터럴(string literal)이 여러 줄에 걸쳐 있을 수 없다는 점입니다.
For example:
X.AddPoint( 25, 100);
X.AddPoint( 0, 75);
// is equivalent to:
X.AddPoint( 25, 100); X.AddPoint( 0, 75);
however...
'Hello World!'
\\is not equivalent to
'Hello
World!'
DelphiScript는 스크립트에서 단일 코드 줄의 길이에 실질적인 제한을 두지 않지만, 가독성과 디버깅 편의성을 위해 화면이나 인쇄물에서 쉽게 읽을 수 있도록 코드 줄 길이를 적절히 제한하는 것이 좋습니다.
코드 줄이 매우 길다면 여러 줄로 나눌 수 있으며, DelphiScript 인터프리터는 이를 한 줄로 작성된 것과 동일하게 처리합니다.
Unformatted code example:
If Not (PcbApi_ChooseRectangleByCorners(BoardHandle,'Choose first corner','Choose final corner',x1,y1,x2,y2)) Then Exit;
Formatted code example:
If Not (PcbApi_ChooseRectangleByCorners(BoardHandle,
'Choose first corner',
'Choose final corner',
x1,y1,x2,y2)) Then Exit;
대소문자 구분
스크립트 작성에 사용되는 DelphiScript 언어는 대소문자를 구분하지 않습니다. 즉, 모든 키워드, 문장, 변수 이름, 함수 및 프로시저 이름은 대문자/소문자 사용과 무관하게 작성할 수 있으며, 대문자와 소문자는 동등하게 취급됩니다.
예를 들어 변수 이름 myVar은 myvar 및 MYVAR과 동일합니다. DelphiScript는 이 모든 이름을 같은 변수로 취급합니다.
유일한 예외는 대화상자 정의의 제목 문자열이나 문자열 변수 값과 같은 리터럴 문자열입니다. 이러한 문자열은 대소문자 차이를 유지합니다.
공백 문자
공백은 스크립트 문장에서 키워드를 구분하는 데 사용됩니다. 그러나 DelphiScript는 문장 내의 추가 공백(white space)을 모두 무시합니다.
예를 들어:
X = 5
// is equivalent to
X =5
공백을 사용해 스크립트의 가독성을 높일 수 있습니다.
스크립트의 함수와 프로시저
DelphiScript 인터프리터는 두 종류의 메서드(프로시저)를 허용합니다: 프로시저(Procedure)와 함수(Function). 함수와 프로시저의 유일한 차이점은 함수는 값을 반환한다는 점입니다.
스크립트에는 메인 프로그램 코드를 정의하는 최소 하나의 프로시저가 있을 수 있습니다. 또한 코드에서 호출할 수 있는 다른 프로시저와 함수를 정의할 수도 있습니다.
Embarcadero Delphi와 마찬가지로, 프로시저와 함수는 Begin-End 문장 블록 내에서 정의됩니다. 함수 또는 프로시저를 호출(Invoke/Call)하려면, 내장 DelphiScript 함수/프로시저를 사용할 때와 동일한 방식으로 문장에 해당 이름을 포함하면 됩니다. 함수 또는 프로시저에 매개변수가 필요하다면 호출 문장에 이를 포함해야 합니다. 함수와 프로시저 모두 매개변수를 받도록 정의할 수 있지만, 호출 문장에 값을 반환하도록 정의할 수 있는 것은 함수뿐입니다.
함수와 프로시저를 정의할 때는 표준 DelphiScript 명명 규칙을 준수하는 한 어떤 이름이든 지정할 수 있습니다.
Typical DelphiScript Procedure:
Procedure CreateSchObjects;
Begin
If SchServer = Nil Then Exit;
SchDoc := SchServer.GetCurrentSchDocument;
If SchDoc = Nil Then Exit;
PlaceSchematicObjects;
SchDoc.GraphicallyInvalidate;
End;
Typical DelphiScript Function:
Function BooleanToString(AValue : Boolean) : String;
Begin
If (AValue) Then Result := 'True'
Else Result := 'False';
End;
함수 이름은 반환값을 설정하는 데 사용할 수 없습니다. 대신 Result 키워드를 사용해야 합니다.
Var, Begin-End global block:
Var
A, B, C;
Begin
B := 10;
C := 20;
A := B + C;
ShowMessage(IntToStr(A));
End;
스크립팅 팁
스크립트 프로젝트에서 스크립트 참조하기
하나의 스크립트에 있는 코드는 동일한 스크립트 프로젝트 내의 다른 스크립트에 있는 프로시저를 호출할 수 있습니다. 어떤 스크립트에 있는 전역 변수든 동일한 프로젝트 내에서 접근할 수 있습니다.
로컬 변수와 전역 변수
스크립트에는 로컬 변수와 전역 변수가 있으므로, 스크립트 프로젝트 내 스크립트들에서 고유한 변수 이름을 사용하는 것이 중요합니다. 변수가 어떤 프로시저나 함수 밖에서 정의되면 전역 변수이며, 동일한 프로젝트의 어떤 유닛에서도 접근할 수 있습니다. 변수가 프로시저 또는 함수 안에서 정의되면 로컬 변수이며, 해당 프로시저/함수 밖에서는 접근할 수 없습니다.
유사한 성격의 스크립트는 하나의 프로젝트에 넣고, 프로젝트 내 스크립트 수는 관리 가능한 규모로 유지하는 것을 권장합니다 — 많은 스크립트에 걸친 전역 변수를 추적하는 것이 문제가 될 수 있습니다. 스크립트를 반드시 스크립트 프로젝트에 저장해야 하는 것은 아니며, 스크립트는 다른 프로젝트 유형에 넣을 수도 있습니다.
고유 식별자와 변수
스크립트 폼을 사용할 때는 모든 스크립트 폼이 고유한 폼 이름을 갖도록 하십시오. 동일한 스크립트 프로젝트에서 모든 스크립트 폼의 이름을 form1 (예: )로 지정하는 것도 가능합니다. 이 경우 스크립트 폼이 실행될 때 올바른 폼을 표시하려고 하면 스크립팅 시스템에 충돌이 발생합니다.
스크립트 폼 이름은 Object Inspector을(를) 사용하여 변경할 수 있습니다. 이름은 스크립트 유닛 파일과 스크립트 폼 파일 모두에서 자동으로 변경됩니다.
매개변수 없는 프로시저 및 함수
스크립트를 실행하기 위해 호출되어야 하는 프로시저는 Select Items to Run dialog에만 표시되도록 스크립트를 작성해야 합니다. 다른 프로시저/함수가 Select Items to Run 대화상자에 표시되지 않도록 하려면, 메서드 이름 옆에 (Dummy : Integer) 매개변수를 삽입할 수 있습니다. 아래 예를 참조하십시오.
// This function is prevented from appearing in the Select Items to Run dialog.
Function TSineWaveform.CreateShape(Dummy : Integer);
Begin
//Do something
End;
{..................................................}
{..................................................}
Procedure TSineWaveform.bCloseClick(Sender: TObject);
var
I : integer;
Begin
//Doing something
Close;
End;
{..................................................}
{..................................................}
procedure DrawSine;
Begin
SineWaveform.showmodal;
End;
DelphiScript 오류 코드
|
Error |
Description |
|---|---|
|
|
스크립트에서 잘못된 문자열이 사용되었습니다. |
|
|
스크립트에서 잘못된 문자열이 사용되었습니다. |
|
|
코드에서 동일한 이름의 함수가 여러 개 존재하는 것은 허용되지 않습니다. 같은 이름을 가진 다른 함수의 이름을 변경하십시오. |
|
|
알 수 없는 식별자입니다. 이 식별자를 사용하기 전에 먼저 선언해야 합니다. |
|
|
스크립트에 유효하지 않거나 알 수 없는 Variable 타입이 있습니다. |
|
|
동일한 유닛 이름이 여러 개 존재하는 것은 허용되지 않습니다. 스크립트 유닛 이름이 고유한지 확인하십시오. |
|
|
유닛 선언이 올바르게 정의되지 않았습니다. |
|
|
스크립트에 함수가 누락되었습니다. |
|
|
DelphiScript가 스크립트를 필요한 내부 컴포넌트에 연결할 수 없습니다. |
|
|
스크립트에 동일한 레이블이 여러 개 존재합니다. 레이블이 고유한지 확인하십시오. |
|
|
선언 블록이 올바르게 정의되지 않았습니다. |
|
|
Goto 레이블이 정의되지 않았습니다. |
|
|
스크립트에 동일한 변수가 여러 개 존재합니다. 변수가 고유한지 확인하십시오. |
|
|
변수 선언 블록에 오류가 있습니다. 선언이 잘못되었거나 스크립팅 시스템이 인식하지 못하는 선언입니다. |
|
|
변수가 정의되지 않아 스크립팅 시스템이 이 변수를 정의할 수 없습니다. |
|
|
메서드 시그니처가 올바르지 않습니다. |
|
|
메서드에 잘못된 매개변수가 사용되었습니다. |
|
|
스크립팅 시스템이 인식하지 못하는 객체 속성입니다. |
|
|
클래스가 아닌 선언을 선언하려고 시도했습니다. |
|
|
스크립트에 선언 오류가 있습니다. |
|
|
스크립트에 구문 오류가 발생했습니다 |
|
|
중복된 식별자 이름 등 유효하지 않은 식별자 이름입니다. 식별자 이름을 다시 정의하십시오. |
|
|
유효하지 않은 식별자입니다. 새 식별자를 다시 정의하십시오 |
|
|
스크립트에서 함수가 올바르게 사용되지 않았습니다 |
|
|
스크립트에서 프로시저가 올바르게 사용되지 않았습니다 |
|
|
16진 상수 값이 올바르게 선언되지 않았습니다. |
|
|
스크립트를 실행하기 전에 먼저 컴파일해야 합니다. 내부 오류입니다. |
|
|
Real 타입 상수 선언 오류입니다. |
|
|
String 타입 상수 선언 오류입니다. |
|
|
스크립팅 시스템이 보고한 알 수 없는 매개변수 타입입니다. |
|
|
스크립트에서 지정된 문자열에 대한 변수 값 결과를 찾을 수 없습니다. |
|
|
스크립트에 프로시저가 누락되었습니다. |
|
|
스크립트에 매개변수가 누락되었습니다. |
|
|
내부 오류입니다. |
|
|
동일한 프로시저 또는 함수가 서로 다르게 선언 및 구현되었습니다. 두 선언의 매개변수를 확인하십시오. |
|
|
메서드/함수/프로시저의 매개변수 중 하나에 올바른 variant 타입이 없습니다. |
|
|
읽기 전용 속성에 값을 설정하려고 했거나, 속성이 존재하지 않습니다. |
|
|
프로시저 또는 함수에 사용된 인수가 스크립트에 유효하지 않습니다. |
|
|
매개변수 값이 누락되었습니다. |
|
|
잘못된 매개변수 타입이 사용되었습니다. |
|
|
이 인터페이스가 선언되거나 정의되지 않았습니다. |
|
|
메서드/함수/프로시저에 필요한 매개변수가 누락되었습니다. |
|
|
DelphiScript가 내부 오류 테이블에 정의되지 않은 알 수 없는 스크립트 오류를 감지했습니다. |
|
|
DelphiScript가 유효하지 않은 오퍼레이션 코드를 감지했습니다. |