본문 바로가기
VisualStudio.C++.C#/코딩팁,함수활용,단편

MFC. Extension DLL. 확장 DLL . 인스턴스핸들 . 리소스 아이디 충돌 해결

by i.got.it 2020. 10. 4.

 

 

MFC extension dll

 

// dllmain.cpp : Defines the initialization routines for the DLL.

static AFX_EXTENSION_MODULE CLibCyMetaTraderDLL = { false, nullptr };

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
	// Remove this if you use lpReserved
	UNREFERENCED_PARAMETER(lpReserved);

	if (dwReason == DLL_PROCESS_ATTACH)
	{
		// Extension DLL one-time initialization
		if (!AfxInitExtensionModule(CLibCyMetaTraderDLL, hInstance))
			return 0;

		// Insert this DLL into the resource chain
		new CDynLinkLibrary(CLibCyMetaTraderDLL);

	}
	else if (dwReason == DLL_PROCESS_DETACH)
	{
		// Terminate the library before destructors are called
		AfxTermExtensionModule(CLibCyMetaTraderDLL);
	}
	return 1;   // ok
}

 

 

Dllmain 함수 인자 dwReason 

- DLL 활용하는 프로세스에서 Dllmain 호출하는 상황에 따라 아래 4가지의 값이 전달됨. 

 

DLL_PROCESS_ATTACH : DLL 사용 프로세스 생성(메모리에 DLL 로딩)시.

DLL_PROCESS_DETACH : DLL 사용 프로세스 종료(메모리에서 DLL 해제)시

DLL_THREAD_ATTACH : DLL 사용 프로세스의 새로운 스레드에서 DLL 로딩시.

DLL_THREAD_DETACH :  DLL 사용 프로세스의 새로운 스레드에서 DLL 해제시.

 

 

new CDynLinkLibrary(CLibCyMetaTraderDLL);

- 리소스 체인에 확장 DLL 을 추가하는것. 

 

- 확장 DLL 을 MFC regular dll 에서 로딩 시 주의사항. 

  - - 확장 DLL이 자체 리소스(대화상자, bmp등 모든 리소스) 기반 구현된것을  MFC regular dll 에서 로딩하려는 경우 확장DLL 에서 자신의 리소스에 접근 못하고 MFC gegular dll 의 리소스가 표현되는 원인이 되므로 필수 주의사항. 

 

처리 요점. 

- new CDynLinkLibrary(CLibCyMetaTraderDLL);  를 Dllmain 에서는 주석처리하고, 외부 노출함수 별도 마련하여 MFC regular dll 에서 해당 노출함수를 호출하여 명시적으로 실행시킬것. 

 

// NOTE: If this Extension DLL is being implicitly linked to by
//  an MFC Regular DLL (such as an ActiveX Control)
//  instead of an MFC application, then you will want to
//  remove this line from DllMain and put it in a separate
//  function exported from this Extension DLL.  The Regular DLL
//  that uses this Extension DLL should then explicitly call that
//  function to initialize this Extension DLL.  Otherwise,
//  the CDynLinkLibrary object will not be attached to the
//  Regular DLL's resource chain, and serious problems will
//  result.

 

 

 

확장 DLL 의 HINSTANCE (인스턴스 핸들) 

 

구조체  AFX_EXTENSION_MODULE 의 멤버변수인 hModule 이 인스턴스 핸들이다. 

 

외부에 인스턴스 핸들을 제공하려면 외부제공용 전역 함수 준비해두면, DLL 활용하는 쪽에서 이 함수 호출하여 DLL 인스턴스 핸들 확보한다.

 


// DLL B의 dllmain.cpp 파일에 추가

// DLL B의 AFX_EXTENSION_MODULE 구조체 참조
extern AFX_EXTENSION_MODULE CyS90LE3CyMetaIPCDLL;

extern "C" __declspec(dllexport) HINSTANCE GetDllBInstance()
{
    // AFX_EXTENSION_MODULE의 hModule 멤버가 DLL의 HINSTANCE임
    return CyS90LE3CyMetaIPCDLL.hModule;
}

 

 

 

 

 

확장 DLL 의 리소스 아이디 충돌문제 해결 방법 

- 확장 DLL 들의 리소스 아이디가 동일한 경우 종종 있다. DLL A 대화상자와 DLL B 대화상자의 리소스 아이디가 1007 으로 동일한 경우 DLL A 에서 DLL B 의 대화상자 표현시 DLL A 의 대화상자가 표현되는 문제 발생한다. 

 

해결방법 

 

 

- 아래 코드 처럼 DLL B 의 인스턴스 핸들 받아서 DLL B 대화상자 표현전에 DLL B 의 리소스가 적용되게 한다. 

 



// DLL A의 코드에서 DLL B의 함수 호출

// DLL B에서 내보낸 함수 선언
extern "C" __declspec(dllimport) HINSTANCE GetDllBInstance();

void ShowDialogFromDLLB()
{
    // DLL B의 인스턴스 핸들 가져옴
    HINSTANCE hInstDllB = GetDllBInstance();

    // 현재 리소스 핸들을 저장
    HINSTANCE hInstOld = AfxGetResourceHandle();
    
    // DLL B의 리소스 핸들로 전환
    AfxSetResourceHandle(hInstDllB);

    // DLL B의 대화상자 생성 및 표시
    CYourDialogB dlgB;  // DLL B의 대화상자 클래스
    dlgB.DoModal();

    // 원래 리소스 핸들로 복원
    AfxSetResourceHandle(hInstOld);
}

 

 

 

위 방법으로 리소스 아이디 충돌 문제 해결 가능하며 아래처럼 별도 클래스 만들어 활용하는 방법도 있다. 

 

RAII 패턴을 사용하는 리소스 핸들 스위처 클래스

- RAAI : Resource Acquisition Is Initialization

 


// Helper 클래스 정의
class CResourceSwitcher
{
    HINSTANCE m_hInstOld; // 이전 핸들을 저장하기 위한 멤버 변수

public:
    CResourceSwitcher(HINSTANCE hNewInst)
    {
        m_hInstOld = AfxGetResourceHandle(); // 이전 핸들 저장
        AfxSetResourceHandle(hNewInst);      // 새 핸들 설정
    }

    ~CResourceSwitcher()
    {
        AfxSetResourceHandle(m_hInstOld);    // 소멸자에서 원래 핸들 복원
    }
};

// 사용 예시
void ShowDialogFromDLLB()
{
    // 자동으로 리소스 핸들 전환 및 복원
    CResourceSwitcher switcher(theAppB.m_hInstance);

    // DLL B의 대화상자를 생성하고 표시합니다.
    CYourDialogB dlgB;  // DLL B의 대화상자 클래스
    dlgB.DoModal();

    // 여기서 CResourceSwitcher 소멸자가 호출되며 원래 리소스 핸들로 복원됨
}

 

 

 

 

 

 

 

 

연관 

 

 

MFC Extension DLL 만들기. ChartDirectorViewer

개요 Visual Studio 2015 MFC extension dll 만들기. 본 글에서 예로 사용되는 "확장DLL 프로젝트" 이름 : ChartDirectorViewer 기능 : Chart Director for C++( http://igotit.tistory.com/553 ) 에서 제공하는..

igotit.tistory.com

 

 

 

 

 

 


첫 등록 : 2020.10.04

최종 수정 : 2024.09.05

단축 주소 : https://igotit.tistory.com/2634


 

 

 

댓글



 

비트코인




암호화폐       외환/나스닥/골드         암호화폐/외환/나스닥/골드
     
현물 |선물 인버스 |선물 USDT       전략매니저(카피트레이딩)         프랍 트레이더 온라인 지원가능. MT4,MT5