비 Visual C++ 개발
시스템 요구사항 섹션에서 설명한 것처럼, Mactel 머신에서의 개발 환경은 Xcode 3.2/4.x, Windows에서는 Microsoft의 Visual C++ 2010입니다. 모든 라이브러리와 헤더 파일들은 이 시스템에서 만들어졌습니다.
또한 API와 다른 유형의 통신을 이용하여 당신의 개발을 다른 환경으로 이동시킬 수 있는 솔루션을 제공합니다.
이 문서는 Microsoft의 Visual C++ 2010과 다른 개발자 환경에서 애드온을 빌드할 수 있는 자세한 설명을 제공합니다. 여기서 Dll_Test 예제도 보실 수 있습니다.
해결해야 할 문제들
당신이 ArchiCAD 애드온 개발의 기본에 익숙하다고 가정합니다. 만약 그렇지 않다면 이 텍스트를 진행하기 전에 해당 문서를 읽으시기 바랍니다. 또한 Dynamic Link Libraries (DLL)의 사용법을 반드시 이해해야 합니다.
ArchiCAD를 위핸 애드온 개발에는 2가지 제한이 있습니다. 첫째, 당신이 사용하는 환경은 반드시 Dynamic Link Library (Win)/ shared library (Mac)를 생성할 수 있어야 합니다. 둘째, 당신은 필수 리소스를 애드온의 구조 페이퍼에서 문서화된 생성된 DLL에 포함시켜야 합니다. 만약 이러한 요구사항들을 충족시킬 수 없다면 당신은 ArchiCAD 애드온을 만들 수 없습니다.
헤더 파일 이용하기
당신의 소스 파일들에 반드시 포함시켜야 하는 몇 가지 헤더 파일들이 있습니다. 이것들은 C++포맷으로만 주어집니다.
만약 당신이 코드를 C나 C++ 언어로 개발하였다면 당신의 DLL을 컴파일하는 것은 매우 쉽습니다. 이 경우 여기서 발견한 헤더 파일들을 직접 사용할 수 있습니다.
통신 라이브러리
당신의 컴파일된 소스 파일들에 링크되어야 하는 정적 라이브러리(ACAP_STAT.lib)가 있습니다.
이 라이브러리는 많은 것들을 처리합니다. 우선 이것은 ArchiCAD와 애드온 간의 모든 통신을 제어합니다. 그리고 또한 이것은 당신의 DLL의 메인 엔트린 포인트를 가지고 있습니다.
만약 당신이 이 라이브러리에 링크할 수 없다면, 당신은 이 기능을 코드화하기 위한 추가 작업을 만들도록 요청 받게 될 것입니다. 이 작업을 가능한 쉽게 할 수 있도록 ACAP_DLL.apx라는 DLL인 라이브러리도 동봉하였습니다.
이 DLL은 반드시 ArchiCAD의 Add-Ons 폴더 안에 있어야 합니다. ArchiCAD가 실행할 때 그것을 찾아보고, 만약 설치되어 있으면 메모리로 로드합니다.
정적 라이브러리와 컴파일된 ArchiCAD 애드온의 작동은 이 DLL을 사용하는 애드온과 비슷합니다. 유일한 차이점은 ArchiCAD 엔진으로 향하는 function call이 실행 EXE 파일을 통해 직접 호출하지 않고 이 통신 DLL을 통해 작동한다는 점입니다. (그림 1)

그림 1: ArchiCAD와 APX 간 통신
이것은 당신의 애드온의 초기화/종료를 직접 다루어야 한다는 것을 의미합니다. 또한 당신은 통신 DLL로부터 필요한 ArchiCAD 함수 어드레스를 가져와야 합니다. 만약 당신이 애드온의 환경을 바르게 초기화했다면, 이후의 개발 및 코드의 작동은 정적 라이브러리에 링크한 것과 동일할 것입니다.
초기화 및 종료 절차
ArchiCAD가 당신의 애드온을 호출할 때, 3가지 주요 초기화 함수들을 호출하게 됩니다. 그래서 이 함수들은 APX 파일로부터 내보내기 되어야 합니다. Microsoft의 Visual C++ 환경에서 개발자에게 주어진 라이브러리는 이 함수들에게 필요한 코드를 포함합니다. 그러나 구현해야 할 것들이 여기에 있습니다.
// --------------------------------------------------------------- // 요구되는 엔트리 포인트들을 서버 애플리케이션으로 전달함 // --------------------------------------------------------------- ACAP_DLL_CLIENT void __ACDLL_CALL GetExportedFuncAddrs (GSPtr expList) { ExpList_ACAP *expPtr; BNZeroMemory (expList, sizeof(ExpList_ACAP)); expPtr = (ExpList_ACAP *) expList; expPtr->version = (API_MAIN_VERSION << 16) | (API_RELEASE_VERSION & 0xFFFF); expPtr->checkenvironment = CheckEnvironment; expPtr->registerinterface = RegisterInterface; expPtr->initialize = My_Initialize; expPtr->freedata = My_FreeData; expPtr->devkitNumber = API_DEVKIT_NUMBER; return; } /* GetExportedFuncAddrs */ // --------------------------------------------------------------- // 서버 애플리케이션으로부터 콜백들을 수신함 // --------------------------------------------------------------- ACAP_DLL_CLIENT GSErrCode __ACDLL_CALL SetImportedFuncAddrs (GSPtr /*impList*/) { return NoError; } /* SetImportedFuncAddrs */ // --------------------------------------------------------------- // 서비스를 실행하기 위해 애드온이 메모리에 로드될 때마다 호출됨 // --------------------------------------------------------------- static GSErrCode __ACDLL_CALL My_Initialize (void* clientId) { gOwnClientID = clientId; GSErrCode err = Initialize (); return err; } /* My_Initialize */ // --------------------------------------------------------------- // 애드온이 메모리로부터 언로드 되기 전마다 호출됨 // --------------------------------------------------------------- static GSErrCode __ACDLL_CALL My_FreeData (void) { GSErrCode err = FreeData (); if (gOwnResModule != NULL) { gFunctionTable->closeownresfile (gOwnResModule); gOwnResModule = NULL; } gOwnClientID = NULL; if (gFunctionTable != NULL) { delete gFunctionTable; gFunctionTable = NULL; } return err; } /* My_FreeData */ |
처음 2개의 함수들은 애드온의 내보내기 절에 포함되어야 합니다. ArchiCAD가 애드온을 시작할 때마다 이전에 종료했을 때 애드온이 메모리에 저장되었는지 여부와 관계없이 이러한 함수들을 호출합니다.
gACAPIDLL
핸들은 GetProcAddress
함수를 이용할 때 통신 DLL을 식별하기 위해 사용될 수 있습니다.
이렇게 하면 당신은 통신 DLL의 배치에 대해 걱정하지 않아도 됩니다.
만약 이 값이 0이면 ArchiCAD가 통신 DLL을 찾을 수 없고 메모리에 로드되지 않았다는 것을 의미합니다.
이 경우 당신의 애드온은 실행될 수 없습니다. 그리고 반드시 종료합니다.
GetExportedFuncAddrs
함수 안에서 당신은 또 다른 2개의 함수 포인터들을 Initialize (My_Initialize
)와
FreeData (My_FreeData
) 함수들에 추가해야 합니다.
둘 다 필수이며 DLL 라이브러리를 로드/프리시킬 경우 항상 호출됩니다.
이 3가지 초기화 함수들을 호출한 뒤에 ArchiCAD는 CheckEnvironment
와
RegisterInterface
함수들을 호출합니다.
그것의 포인터는 GetExportedFuncAddrs
함수를 통해 돌려 받게 됩니다.
메인 초기화 함수들 이후에 애플리케이션의 다른 리소스들을 초기화하는 것을 기억하십시오. 마침내 당신의 애드온이 끝나게 되면 그것들로부터 메모리를 프리시키는 작업을 잊지 마십시오.
함수 어드레스 가져오기
애드온이 gACAPIDLL
의 값을 가져온 뒤에, GetProcAddress
함수들의 연속 사용을 통해
필요한 함수들의 주소들을 가져올 수 있습니다. 통신 DLL의 이름은 ACAP_DLL.APX입니다.
버전 제어에 대해 신경 쓸 필요 없습니다.
만약 그것의 인스턴스 핸들을 가져온다면, 요구되는 통신의 버전이 설치되어 구현되어 있음을 확신할 수 있습니다.
ArchiCAD 함수를 사용하는 방법은 type을 define하고, 그 type의 변수를 만들고,
그 값을 GetProcAddress
함수를 이용해 set합니다. 그리고 나서 그것을 이용해 호출할 수 있습니다.
샘플은 그림 3에서 보실 수 있습니다.
typedef GSErrCode (__ACENV_CALL *acapi_attribute_getProc) (ClientID clientID, API_Attribute *attribute); gFunctionTable->acapi_attribute_get = (acapi_attribute_getProc) GetProcAddress (gACAPIDLL, "ACAPI_Attribute_Get"); |
리소스 이용하기
당신의 책임은 당신의 ArchiCAD 애드온의 올바른 리소스를 사용하는 것입니다. 당신의 개발 환경은 리소스 파일을 DLL에 링크할 수 있는 기능을 가져야 합니다. 해당 리소스를 만들려면 관련 API 문서를 참조하십시오.