반응형
Ø

라이브러리란?
특정한 코드(함수 혹은 클래스)를 포함하고 있는 컴파일된 파일이다.

라이브러리를 만드는 이유?
 자주 사용되는 특정한 기능을 main 함수에서 분리시켜 놓음으로써, 프로그램을 유지, 디버깅을 쉽게하고 컴파일 시간을 좀더 빠르게 할수 있기 때문이다.

라이브러리에도 그 쓰임새에 따라서 여러가지 종류가 있다(크게 3가지). 가장 흔하게 쓰일수 있는 "정적라이브러리"와 "공유라이브러리", "동적라이브러리" 가 있다.

이들 라이브러리가 서로 구분되어지는 특징은 적재 시간이 될것이다.

정적라이브러리

정적라이브러리는 object file(.o로 끝나는) 의 단순한 모음이다. 정적라이브러린느 보통 .a 의 확장자를 가진다. 간단히 사용할수 있다. 컴파일시 적재되므로 유연성이 떨어진다. 최근에는 정적라이브러리는 지양되고 있는 추세이다. 컴파일시 적재되므로 아무래도 바이너리크기가 약간 커지는 문제가 있을것이다.

공유라이브러리

공유라이브러리는 프로그램이 시작될때 적재된다. 만약 하나의 프로그램이 실행되어서 공유라이브러리를 사용했다면, 그뒤에 공유라이브러리를 사용하는 모든 프로그램은 자동적으로 만들어져 있는 공유라이브러리를 사용하게 된다. 그럼으로써 우리는 좀더 유연한 프로그램을 만들수 잇게 된다.

정적라이브러리와 달리 라이브러리가 컴파일시 적재되지 않으므로 프로그램의 사이즈 자체는 작아지지만 이론상으로 봤을때, 라이브러리를 적재하는 시간이 필요할것이므로 정적라이브러리를 사용한 프로그램보다는 1-5% 정도 느려질수 있다. 하지만 보통은 이러한 느림을 느낄수는 없을것이다.

동적라이브러리

공유라이브러리가 프로그램이 시작될때 적재되는 반면 이것은 프로그램시작중 특정한때에 적재되는 라이브러리이다. 플러그인 모듈등을 구현할때 적합하다. 설정파일등에 읽어들인 라이브러리를 등록시키고 원하는 라이브러리를 실행시키게 하는등의 매우 유연하게 작동하는 프로그램을 만들고자 할때 유용하다.

– MS VC++  라이브러리 만들기


사용자 삽입 이미지
1.project name란에 라이브러리 이름 작성
사용자 삽입 이미지
사용자 삽입 이미지












2.test.c 파일을 생성한다.(함수 정의(구현)부분에 대한 내용)

3.test.h 파일을 생성한다.(함수의 선언부분이 있는곳)

사용자 삽입 이미지

 
//나만의 덧셈 라이브러리 만들기
#include <stdio.h>
#include "test.h"
//덧셈 함수 구현부분
int Add(int a,int b)
{
   return a+b;
}




3.test.h 에 함수에 대한 선언
   ex> int Add(int a, int b);
4.컴파일 하면 Debug 디렉토리 안에 프로젝트명.lib 이 생성

그 다음은 헤더파일을 해당 프로젝트에 넣고 라이브러리 링크
시키면 사용됨.

C로 만든 라이브러리를 C++ 프로젝트에 사용할때는 주의를 하자.
컴파일 과정에서 만들어진 라이브러리의 함수명이 차이가 있다.
C 로 만든 라이브러리는 C프로젝트에서..
C++로 만든 라이브러리는 C++프로젝트에서..
다른 방법으로는 위에 글에 설명..
반응형

네임드 커널 오브젝트를 사용한 중복 실행 방지법.

1. Introduction

윈도우상에서 구동되는 특정 애플리케이션들의 경우 중복 실행이 방지되어야 한다. 대표적으로 MSN 메신저등을 들 수 있다. 메신저의 경우 중복해서 실행될 필요가 없다. 이렇게 한번만 실행되어야 하는 프로그램의 경우 어떻게 구현할 수 있을까? 윈도우 핸들을 찾는 방법, 커널 오브젝트를 사용하는 방법, 공유 세그먼트를 사용하는 방법 등이 있다. 여기서 우리가 구현할 방법은 그 중에서도 커널 오브젝트를 사용한 방법이다.

2. Single Instance

커널 오브젝트를 사용해서 어떻게 중복 실행을 방지할 수 있을까? 원리는 네임드(Named) 커널 오브젝트의 경우 프로세스 사이에 공유 된다는 점 이다. 이 점을 이용하면 다음과 같은 시나리오를 생각할 수 있다. 프로그램 시작시에 네임드 커널 오브젝트를 생성한다. 그리고 프로그램이 종료할 때 해당 오브젝트를 닫는다. 이렇게 되면 한번이라도 해당 프로그램이 실행되어 있으면 그 오브젝트가 생성되어 있는 셈이 된다. 만약에 두 번째 프로그램이 실행된 경우에 또 커널 오브젝트를 생성하려고 하면 커널에서는 이미 열러진 오브젝트 핸들을 넘겨주면서 해당 오브젝트의 레퍼런스 카운트를 1증가 시킨다. 그리고 끝으로 GetLastError값으로 ERROR_ALREADY_EXISTS를 설정한다. 따라서 간단히 우리는 커널 오브젝트 생성후 GetLastError를 조사해서 ERROR_ALREADY_EXISTS면 이미 프로그램이 한번 이상 실행되었다고 간주할 수 있다.

아래는 이러한 부수적인 작업들을 한번에 처리해주는 클래스의 소스다. 해당 클래스를 전역 내지는, 프로그램의 존속 기간동안 살아있는 클래스의 멤버 변수로 만든후에 IsExist함수를 호출해서 조사하면 된다. 만약 해당 값이 TRUE를 리턴한다면 프로그램을 바로 종료시키면 된다.
 

  1. class CSingleInstance  
  2. {  
  3. private:  
  4.         HANDLE  m_hMutex;  
  5.           
  6. public:  
  7.         CSingleInstance(LPCTSTR lpszMutexName = "SingleMutex");  
  8.         ~CSingleInstance();  
  9.           
  10.         BOOL IsExist() {return m_hMutex==NULL;}  
  11. };  
  12.  
  13. CSingleInstance::CSingleInstance(LPCTSTR lpszMutexName)  
  14. {  
  15.         m_hMutex = CreateMutex(NULL, TRUE, lpszMutexName);  
  16.         if(GetLastError() == ERROR_ALREADY_EXISTS)  
  17.         {  
  18.                 CloseHandle(m_hMutex);  
  19.                 m_hMutex = NULL;  
  20.         }  
  21. }  
  22.  
  23. CSingleInstance::~CSingleInstance()  
  24. {  
  25.         if(m_hMutex)  
  26.         {  
  27.                 CloseHandle(m_hMutex);  
  28.                 m_hMutex = NULL;  
  29.         }  
  30. }     
  31.      

3. How to use it?

그럼 실제로 MFC 프로그램에서 한번 사용해 보자. 일단 위 클래스 소스를 적당한 위치에 복사한다. 그리고 app 클래스의 멤버 변수로 아래와 같이 선언한다.

  1. CSingleInstance m_inst;  

그 다음은 app 클래스의 InitInstance 제일 앞에 아래와 같이 추가해보자.

  1. if(m_inst.IsExist())  
  2. {  
  3.         AfxMessageBox("다른 곳에 실행된 놈이 있습니다.");  
  4.         return FALSE;  
  5. }     
  6.      

그리고 프로그램을 실행해보면 두번이상은 실행이 되지 않는 것을 확인할 수 있다. 주의해야 할 점은 위 클래스의 뮤텍스 이름은 클래스의 생성자로 전달된다는 것이다. 따라서 뮤텍스 이름을 지정하고 싶은 경우에는 C++의 초기화 리스트를 사용해서 초기화 해야 한다.
------------------------------------------------------------------------------------------

※ 윈도우 핸들을 찾는 방법

FindWindow(LPCTSTR lpszClassName,  LPCTSTR lpszWindowName) 함수를 이용해 찾으면 된다.(이 때, 인수 값을 NULL로 넣으면 그 인수는 검색에서 제외한다.)

app 클래스의 InitInstance 메서드에 다음과 같이 추가하면 된다.

if (pWndPrev=FindWindow(NULL,"프로그램타이틀")) {
  if (pWndPrev->IsIconic())  pWndPrev->ShowWindow(SW_RESTORE);

   pWndChild = pWndPrev->GetLastActivePopup();
  pWndChild->SetForegroundWindow();

  return FALSE;
}


※ 네임드(Named) 커널 오브젝트를 이용하는 방법

프로세스간 공유가 가능한 뮤텍스나, 세마포어와 같은 네임드 커널 오브젝트를 사용하면 된다.
프로그램 실행시에 오브젝트를 생성하고 프로그램 종료시에 오브젝트를 제거하면, 프로그램 실행 중에는 오브젝트가 생성되어 있으므로 만약에 두 번째 프로그램이 실행된 경우에 또 오브젝트를 생성하려고 하면 커널에서는 이미 열러진 오브젝트 핸들을 넘겨주면서 해당 오브젝트의 레퍼런스 카운트를 하나 증가 시킨다. 그리고 끝으로 GetLastError값으로 ERROR_ALREADY_EXISTS를 설정한다.

app 클래스의 InitInstance 메서드에 다음과 같이 추가하면 된다.

g_hMutex = CreateMutex(NULL, TRUE, "프로그램이름아무거나");  

if(GetLastError() == ERROR_ALREADY_EXISTS)  {  
   CloseHandle(g_hMutex);
   g_hMutex = NULL;

  return FALSE;
}

그리고 프로그램 종료시(OnDestroy 등)에는 뮤텍스를 해제하는 내용을 추가한다.

if (g_hMutex!=NULL)  ReleaseMutex(g_hMutex);

+ Recent posts