Jul 12 2007
[C/C++]함수 포인터를 이용한 DLL과 사용 프로그램 간의 양방향 호출
DLL을 사용한 프로그램을 구현하다 보면 단방향 호출이 상당히 불편할 때가 많다.
DLL은 dllimport/dllexport를 통해 함수 (혹은 AFX_EXT_CLASS 등으로 클래스) 를 노출시킴으로써 DLL을 사용하는 측에서 호출할 수 있지만, 역으로 DLL을 사용하는 측의 함수를 DLL에서 사용해야 할 일이 생긴다면?
이럴 때 ‘함수 포인터’를 이용하면 간단히 해결할 수 있다.
상황을 하나 설정해 보자.
DLL 내부의 동작 로직상 고유의 ID를 얻어야 하는데, 이 ID 값은 외부 프로그램에서 제공한다.
그리고 그 ID 값은 필요할 때마다 새로 생성할 수 있어야 한다.(즉, 로직 내에서 ID가 몇개 필요할지는 예측할 수 없다)
이럴 경우 ID 갯수 예측을 할 수 없기 때문에 DLL 배포함수에 전달인자로 ID 리스트를 넘기는 방법을 사용할 수가 없고, 외부 프로그램에서 ID를 생성하는 함수를 DLL 배포함수를 통해 함수 주소를 넘겨주고, DLL에서는 ID 생성이 필요할 때 마다 함수 포인터를 사용하여 외부 함수를 사용하는 방법으로 문제를 해결해야 한다.
소스 코드로 설명하자면,
// DLL 배포 함수를 모은 헤더 파트(외부 배포 및 내부 사용 겸용)
// 프로젝트에서 DLL에는 _MYDLL_을 predefine 에 꼭 넣어줄 것
#ifdef _MYDLL_
#define MY_DLL_DIST __declspec(dllexport)
#else
#define MY_DLL_DIST __declspec(dllimport)
#endif _MYDLL_// ID를 얻어오는 함수를 외부 프로그램으로부터 등록받는 배포함수
void MY_DLL_DIST RegisterIDRetriveFunc( BOOL (*fpGetID)(char *pszIDBuf, int nBufLength) );
// RegisterIDRetriveFunc의 구현부
// ID를 얻어오는 함수의 포인터를 전역 변수로 저장할 것임
// 등록이 되지 않은 상태는 NULL로 표시
BOOL (*fpGetNewID)(char *pszID, int nBufLength) = NULL;…
void MY_DLL_DIST RegisterIDRetriveFunc( BOOL (*fpGetID)(char *pszIDBuf, int nBufLength) )
{
// 전역 함수 포인터에 외부 함수를 등록
fpGetNewID = fpGetID;
}// 이후에 사용할 때의 예제
// BOOL bSuccess = (*fpGetNewID)(pszBuf, nBufLen);
// 외부 프로그램의 소스
BOOL GetID(char *pszIDBuf, int nBufLength)
{
…
}…
// DLL 에 함수를 등록
RegisterIDRetriveFunc(&GetID);
외부 프로그램에서는 ID를 얻을 수 있는 함수의 주소를 전달인자로 하여 RegisterIDRetriveFunc()를 호출하고, DLL에서는 RegisterIDRetriveFunc의 전달인자로 넘겨받은 함수 주소를 가지고 DLL 내부에서 보관하고 있다가 필요할 때 함수 포인터 형식으로 호출하면 된다.
