통신 관리자
통신 관리자는 API v3.1에서 도입된 매우 강력한 새로운 서비스입니다.
이전 버전에서는 API 애드온들은 ArchiCAD에 의해서만 호출될 수 있었습니다. 그 당시에는 2가지 방법이 있었습니다. 애드온은 직접적인 사용자 상호작용에 의해 호출되거나 알림을 게시할 필요가 있었습니다. 애드온이 다른 애드온을 호출하는 방법은 없었습니다.
API v3.1부터 애드온은 서로 호출할 수 있게 되었습니다.
모든 통신 관리자 함수들은 ACAPI_Command_ 접두사로 시작합니다. 함수들은 다음과 같습니다:
ACAPI_Command_Test
ACAPI_Command_Call
ACAPI_Command_ExternalCall![]()
몇 가지 함수들은 파라미터 전달을 위한 쉽고 제어된 메커니즘을 제공합니다. 다음과 같습니다:
APIAny_InitMDCLParameterListID
APIAny_GetMDCLParameterNumID
APIAny_GetMDCLParameterID
APIAny_AddMDCLParameterID
APIAny_ChangeMDCLParameterID
APIAny_FreeMDCLParameterListID
엔트리 포인트
애드온의 엔트리 포인트는 무엇입니까? 이것은 통신 관리자의 지원을 통해 또 다른 애드온으로부터 호출될 수 있는 함수 또는 서비스입니다.
엔트리 포인트들은 인터페이스에 독립적입니다. ArchiCAD 메뉴 구조에 넣는 커맨드와 엔트리 포인트 간에는 아무런 관계가 없다는 것을 의미합니다. 첫 번째 세트는 ACAPI_Register_Menu Ehsms ACAPI_Register_FileType 등에 의해 제어되며, 두 번째 타입 엔트리 포인트들은 ACAPI_Register_SupportedService에 의해 주어집니다.
등록
애드온은 원하는 만큼 여러 개의 엔트리 포인트들을 가질 수 있으며, 각각의 진입점은 ACAPI_Register_SupportedService를 사용하여 당신의 애드온의 RegisterInterface 함수에 등록되어야 합니다. 이 함수는 애드온이 다른 애드온에 의해 호출될 수 있음을 ArchiCAD에게 알려줍니다. 이 함수의 파라미터들은 다음과 같습니다:
- 엔트리 포인트의 식별자,
- 엔트리 포인트의 버전,
더 자세한 내용은 함수 설명을 참고하십시오.
나중에 Initialize 함수에서 애드온은 다른 지원되는 커맨드들을 처리하기 위해 콜백 함수를 등록해야 합니다. ACAPI_Install_ModulCommandHandler 함수의 파라미터들은 (ID와 버전 넘버와 함께) 커맨드를 식별하고, 마지막 파라미터는 모듈 커맨드 핸들러 콜백 함수를 공급합니다. 그러면 이 콜백 함수는 파라미터들을 수신하고, 선택적으로 그 결과를 별도의 포인터로 전달 받을 수 있으며, 사일런트 모드로 실행되어야 하는지 여부도 공지 받게 됩니다.
엔트리 포인트 식별
엔트리 포인트는 다음 2가지 컴포넌트에 의해 식별됩니다:
- 애드온 식별자. 이 목적을 위해 API는 'MDID' 리소스를 사용합니다. 그것을 식별하기 위해 단순히 대상 애드온의 ID를 API_ModulID structure에 넣으면 됩니다.
- 엔트리 포인트 식별자. 이것은 대상 애드온이 사용한 ACAPI_Register_SupportedService의 1번째 파라미터와 동일해야 합니다.
- 엔트리 포인트의 버전.
이것은 엔트리 포인트 ID들이 하나의 애드온 세계에서 유일해야 한다는 것을 의미합니다. 서로 다른 애드온들은 동일한 엔트리 포인트 ID들을 가질 수 있지만 지역적으로 하나의 애드온은 동일한 ID를 여러 개 지정할 수 없습니다.
호출자 애드온 측에서는 ACAPI_Register_RequiredService 함수를 이용하여 RegisterInterface 함수 안에서 대상 애드온의 필수 엔트리 포인트들의 존재 여부를 확인합니다.
버전 제어
마지막 이슈는 버전 컨트롤입니다. 호출자 애드온은 요구되는 엔트리 포인트의 버전 역시 지정해야 합니다. API는 역호환성을 가정합니다. 어떤 애드온이 엔트리 포인트의 가용성에 대해 테스트할 때, 다음 경우들이 발생할 수 있습니다(식별을 성공했다고 가정함):
- 엔트리 포인트 버전이 요청한 것보다 작습니다. 이 경우 오류가 리턴됩니다.
- 엔트리 포인트 버전이 요청한 것과 같거나 큽니다. API는 역호환성을 가정하므로 성공적으로 리턴됩니다.
당신이 어떤 엔트리 포인트에게 버전 번호를 할당할 때, 당신은 다음 규칙들을 지켜야 합니다:
- 역호환성을 보장할 수 있을 때, 단순히 버전 번호를 증가시킵니다.
- 호환성을 보장할 수 없을 때, 엔트리 포인트 식별자를 변경합니다.
호환성 이슈가 중요한 대부분의 일반적인 경우는 다음과 같다는 것을 참고하십시오:
- 인터페이스 내에서 변경사항이 있습니다. (호출자가 전달할 수 있는 파라미터들은 변경되어야 함)
- 알고리즘 내에서 변경사항이 있습니다. (동일한 파라미터들이 전달되었을 때 출력이 다름)
어느 경우든 가능하면 호환성을 유지합니다. 엔트리 포인트의 호출시, 통신 관리자는 먼저 커맨드를 식별합니다. 만약 가능하다면 엔트리 포인트 버전을 확인합니다. 만약 버전 문제가 없다면, 필요한 버전 번호를 전달하여 엔트리 포인트를 호출합니다. 동일한 환경과 동작을 보장하기 위해 이 데이터를 사용하십시오.
실행의 제어
API가 애드온을 호출했을 때 뒤에서 무슨 일이 발생하는지 이해하는 것은 매우 중요합니다.
일반적으로 API는 각 실행된 애드온에게 동일한 환경을 할당합니다. 보통 오직 하나의 애드온이 API에 의해 실행합니다. 콜백 함수 안에 하나의 애드온만 있습니다. 그러나 호출 스택 안에 여러 개의 애드온들이 있을 경우가 있습니다.
- 특정 애드온들에게 알림을 게시할 필요가 있을 때
- 애드온은 다른 애드온의 기능을 호출할 권리를 갖고 있습니다.
이러한 경우 여러 애드온들이 동시에 실행되며 모두 알림 또는 모듈 커맨드 핸들러 함수들 안에 있습니다.
이것은 진짜 멀티 프로세싱 아키텍처가 아니라는 것을 참고하십시오.
API는 항상 호출 스택을 유지하며, 가장 위에 있는 애드온만 API 서비스들을 호출할 수 있는 권한을 갖고 있습니다. 이것이 환경이 활성화된 애드온입니다. 일단 가장 위에 있는 애드온이 콜백 함수에서 리턴되면 API는 스택에 다음 애드온을 올리고 그것의 환경을 활성화시킵니다.
그래서 구조가 평행이 아닌 중첩(nested)입니다.
아래 그림은 시스템을 설명하려고 한 것입니다. 사용자가 애드온 A 안에 구현되어 있는 어떤 커맨드를 호출했습니다. 애드온 A는 애드온 B의 함수를 호출합니다. 이것은 애드온 C에 알림을 게시하는 동작을 수행합니다.
그림 #1: API 호출 스택과 클라이언트 환경
수직 선들은 환경이 활성화된 것들을 보여줍니다. 오른쪽은 API가 관리하는 호출 스택을 보여줍니다.
그림 #2에서는 CommunicationManager와 CommunicationClient 예제 프로젝트가 서로 어떻게 통신하는지를 볼 수 있습니다.
그림 #2: 통신 아키텍처
그림의 왼쪽은 일반적인 상황을 보여줍니다.
클라이언트 A(CommunicationManager 예제 프로젝트)는 클라이언트 B(CommunicationClient 예제 프로젝트)의 엔트리 포인트 'CMD1'
(command 1)를 호출하고 싶어합니다.
이것은 필수 ID들을 가지고 ACAPI_Command_Call 함수를 호출합니다.
API는 애드온 B를 로드하고 'CMD1'
커맨드에 등록된 모듈 커맨드 핸들러 함수를 호출합니다.
B가 리턴되었을 때, 제어권은 API로 돌아가 ACAPI_Command_Call 함수로 가게 됩니다.
A가 소유한 환경으로 다시 전환하고 리턴합니다. 클라이언트 A는 제어권을 얻고 계속 작업을 진행할 수 있습니다.
이 시스템은 매우 간단하지만 때때로 충분히 강력하지 않습니다. ACAPI_Command_Call 함수는 오버헤드가 많은 매우 강력한 함수입니다. 우선, 호출될 애드온이 설치되어 있는지 여부를 확인해야 합니다. 그 후에 메모리로 로드되고 초기화되어야 합니다; 물론 예전에 로드되지 않았을 경우입니다. 호출자 애드온은 일부 파라미터들을 전달하고 싶을 경우도 있습니다. 이를 수행하는 메서드 역시 오버헤드에 강합니다. (이 페이퍼의 뒤에서 자세히 설명합니다)
그림 오른쪽에는 더 복잡한 아키텍처를 보여줍니다. 이것은 두 애드온들이 직접 서로를 호출할 수 있습니다. 이를 위해서 클라이언트 B는 2개의 특수 엔트리 포인트들이 구현되어 있어야 합니다:
'BEGB'
는 바이너리 링크를 구축합니다. 실제로는 함수 테이블을 채우거나 가상 함수들을 가진 초기화된 클래스에 대한 포인터를 리턴합니다. 가장 중요한 것은 API가 메모리 안에 유지되도록 ACAPI_KeepInMemory 함수를 호출하는 것입니다. ACAPI_Command_Call 함수가 클라이언트 A에게 리턴되면, 그것은 필수 함수 포인터들을 얻게 되고, 클라이언트 B가 메모리 안에 있기 때문에 유효하며 호출될 수 있습니다. 이 시점부터 클라이언트 A는 클라이언트 B에게 함수 포인터들을 전달할 수 있게 됩니다. 이제 애드온들이 통신 관리자의 도움 없이 표준 C/C++ 호출로 서로 직접 호출할 수 있는 환경이 구축되었습니다.'ENDB'
는 바이너리 링크를 폐기합니다. 실제로 해야 할 일은 그것이 언로드될 수 있도록 신호를 주기 위해 ACAPI_KeepInMemory 함수를 호출하는 것입니다.
무엇을 아는 것이 가장 중요하냐면, 이 아키텍처에서 클라이언트 B가 클라이언트 A의 API 환경에서 실행 중이라는 것입니다. 클라이언트 B는 API 서비스들 중 아무거나 호출할 수 있지만, API는 클라이언트 A를 활성화된 것으로 처리합니다. API는 클라이언트 A가 호출하는 것처럼 이러한 요청을 처리하게 됩니다. 이 중요한 세션은 그림에서 지그재그 형식 선으로 표시됩니다.
ArchiCAD 10부터 다른 프로젝트 파일에서 작업을 수행하기 위해
외부 ArchiCAD 인스턴스에서 애드온 커맨드를 실행할 수 있다는 것을 참고하십시오.
더 자세한 것은 ACAPI_Command_ExternalCall 함수를 참고하십시오.
파라미터 전달
파라미터들은 ACAPI_Command_Call 함수의 params
인수에 전달되어야 합니다.
이 핸들은 API가 소유하고 있습니다. (내부 포맷은 공개되어 있지 않음) 내용은 API가 확인하지 않습니다. 단지 호출된 엔트리 포인트에게 전달될 뿐입니다.
파라미터들은 애드온의 public 헤더 파일 안에 리스트화 되어야 합니다. 각 파라미터는 이름으로 식별됩니다. 각 파라미터는 값 타입을 가지고 있는데 문자열, integer, float 타입이 될 수 있습니다. API는 전달된 파라미터들을 확인하지 않습니다. 단지 호출된 애드온에게 전달합니다. 호출되는 애드온의 엔트리 함수에서 일관성을 검증해야 합니다.
워크플로우는 다음과 같습니다:
- 호출자 애드온은 APIAny_InitMDCLParameterListID 함수로 파라미터 리스트를 초기화해야 합니다,
- 요청된 파라미터들은 APIAny_AddMDCLParameterID 함수로 이 리스트에 이어 붙일 수 있습니다,
- 호출된 애드온은 전달된 파라미터들을 APIAny_GetMDCLParameterNumID와 APIAny_GetMDCLParameterID 함수들로 분해할 수 있습니다,
- 파라미터들은 APIAny_ChangeMDCLParameterID 함수로 변경될 수 있습니다.
- 파라미터 리스트는 호출자가 APIAny_FreeMDCLParameterListID 함수로 폐기해야 합니다.
파라미터들이 호출된 애드온의 공장 기본값 파라미터들에게 상대적이어야 한다는 것은 매우 중요합니다.
호출된 애드온은 먼저 공장 기본값 파라미터들로 설정해야 합니다. 그리고 나서 전달된 값들을 하나씩 가져오는 동안 기본값은 변경되어야 합니다.
만약 전달된 파라미터가 하나도 없다면 (params == NULL
) 공장 기본값 파라미터들은 변경하지 않고 사용되어야 합니다.
다른 중요한 참고사항은 파라미터들이 전달된 순서대로 통역되어야 한다는 것입니다.
위의 규칙들은 엔트리 포인트들의 실행이 컨텍스트에 민감하지 않도록 보장해 줍니다. (Preferences에 저장된) 현재 기본값이 무엇이든지, 파라미터들은 공장 기본값을 기반으로 통역됩니다. 일부 파라미터들이 클라이언트에게 전달되지 않아도 상관 없습니다. 왜냐하면 그것들은 기본값들을 갖고 있기 때문입니다.
예제를 하나 보겠습니다.
DXF/DWG 애드온은 AutoCAD 도면을 여는 엔트리 포인트를 내보냅니다. 옵션 다이얼로그는 또한 공장 기본값 파라미터들을 설정하고 사용하는 Default 버튼을 갖고 있습니다. 애드온은 전달된 파라미터들을 통역하는 동안 이 다이얼로그의 행동을 에뮬레이트합니다.
인터페이스 제어
호출자 애드온은 silentMode
파라미터를 이용하여 호출된 애드온의 모든 인터페이스 요소들을 비활성화할 수 있습니다.
만약 이 파라미터를 true
로 세트하면, 호출된 애드온은 자신의 다이얼로그나 경고창을 열수 없습니다.
false
인 경우, 옵션 다이얼로그가 반드시 나타납니다; 물론 전달된 파라미터들이 처리된 후에 말입니다.
사용자는 어떤 파라미터든 변경할 수 있습니다. 변경사항이 전달된 파라미터들에게 영향을 미칠 수 있는 경우,
호출자가 변경사항을 추적할 수 있도록 APIAny_ChangeMDCLParameterID 함수를 사용하십시오.
리턴 값
호출자에게 파라미터들을 리턴하는 2가지 방법이 있습니다.
기본 옵션은 ACAPI_Command_Call 호출의 리턴 값을 이용하는 것입니다. 이 함수에 의해 리턴된 값은 클라이언트의 모듈 커맨드 핸들러 함수에 의해 리턴된 값입니다.
다른 방법은 resultData
파라미터를 이용하는 것입니다. 이것은 아무 목적으로나 사용될 수 있는 단순 포인터입니다. 사양은 호출된 애드온에 의해 주어져야 합니다.
문서
인터페이스를 게재하는 각 애드온에 대하여 개발자 문서를 제공하는 것은 절대적으로 필요합니다. 이 문서는 앤트리 포인트의 기능이 무엇인지, 어떤 파라미터들이 전달되는지, 그것들이 어떻게 통역되는지, 그리고 어떤 리턴된 값들이 제공되는지에 대한 세부사항들을 제공해야 합니다.
기본적으로 이 문서를 애드온이 설치된 폴더에 넣습니다.