//////////////////////////////////////////////////////////////////////////
#include "tlhelp32.h" ==> h 필요.
void _LibProcSafeKill(); ==> function으로 작성.
//////////////////////////////////////////////////////////////////////////

 

void _LibProcSafeKill()
{
HANDLE hProcessSnap;
HANDLE hProcess;
DWORD dwPriorityClass;
CString strModuleName;
PROCESSENTRY32 pe32;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessSnap == INVALID_HANDLE_VALUE) return;

// Set the size of the structure before using it.
pe32.dwSize = sizeof(PROCESSENTRY32);

// Retrieve information about the first process,
// and exit if unsuccessful
if(!Process32First(hProcessSnap, &pe32))
{
CloseHandle(hProcessSnap); // Must clean up the snapshot object!
return;
}

// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
// Retrieve the priority class.
dwPriorityClass = 0;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
if(hProcess == NULL)
continue;

strModuleName = (LPCTSTR)pe32.szExeFile;
strModuleName.MakeLower();
if(strModuleName.Find(_T("tos.exe")) > -1)
{
DWORD dwExitCode;
::GetExitCodeProcess(hProcess, &dwExitCode);
::TerminateProcess (hProcess, dwExitCode);
CloseHandle(hProcess);
break;
}
CloseHandle(hProcess);
} while(Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
}

 

time_t timer;
struct tm *t;
/* gets time of day */
timer = time(NULL);
/* converts date/time to a structure */
t = localtime(&timer);
sprintf(today"%04d-%02d-%02d", t->tm_year+1900, t->tm_mon+1, t->tm_mday);

먼저,

1. resource에 RichEdit를 집어넣자.!!!

2. AfxInitRichEdit() 함수를 콜하자.. 그래야 실행이 된다.

 

// CPG_XXX 생성

CPG_XXX::CPG_XXX()
{
AfxInitRichEdit( );
}
// initInstance() ..... 윗부분에 있음.

 

3. 변수와 연결시켜줍니다.

DDX_Control(pDX, IDC_CMDMSG, m_cmdmsg);

 

4. 원하는 폰트를 설정하기.

xxx.h 선언.

CFont m_Font2;

 

xxx.cpp Oninitdialog() 선언.

m_Font2.CreateFont(16, 0, 0, 0, FW_NORMAL , FALSE, FALSE, 0,

ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,

DEFAULT_QUALITY, FF_SWISS, "Tahoma");
m_cmdmsg.SetFont(&m_Font2);

 

5. RichEdit 꾸미기.

m_cmdmsg.SetTargetDevice(NULL, 0); // CDC 독립적으로 수행되도록 ??
m_cmdmsg.SetReadOnly();
m_cmdmsg.SetBackgroundColor(FALSE, RGB(0,0,0));

 

//the changer According to kind value.

#define NORMAL 0
#define FAIL 1
#define PASS 2

// color status.

#define P_COLOR RGB(200,157,21)
#define F_COLOR RGB(255,0,0)
#define N_COLOR RGB(88,228,106)

 

// RichEditCtrl 처음 초기화를 위하여 작업

void CPG_SendDlg::CmdMsgBoxInit(int kind, CString strbuf)
{

CHARFORMAT cf;
// Initialize character format structure
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_COLOR;
cf.dwEffects = 0; // To disable CFE_AUTOCOLOR
cf.yHeight = 200;
switch(kind){
case NORMAL: cf.crTextColor = N_COLOR; break;
case FAIL: cf.crTextColor = F_COLOR; break;
case PASS: cf.crTextColor = P_COLOR; break;
}

m_cmdmsg.SetWordCharFormat(cf);
//strbuf+="\r\n";
int nOldLines = 0, nNewLines = 0, nScroll = 0;
long nInsertionPoint = 0;
nOldLines = m_cmdmsg.GetLineCount();
nInsertionPoint = m_cmdmsg.GetWindowTextLength();
int cline=m_cmdmsg.GetLineCount();
m_cmdmsg.ReplaceSel(strbuf);

 

int nline=m_cmdmsg.GetLineCount();
int scroll=nline-cline;
m_cmdmsg.SetCaretPos(CPoint(0,m_cmdmsg.GetLineCount()-1)); // Auto Scroll
m_cmdmsg.LineScroll(scroll);

 

ClearCmdMsgBox(0);
}

 

#define MAXMSGCNT 500

// RichEditContext Clear.

void CPG_SendDlg::ClearCmdMsgBox(int mode)
{
int maxcnt=0;
static int msgcnt=0;
msgcnt++;
if(mode == 0) maxcnt = MAXMSGCNT;
else maxcnt = 0;
if(msgcnt > maxcnt)
{
m_cmdmsg.LockWindowUpdate();
m_cmdmsg.SetWindowText("");
m_cmdmsg.UnlockWindowUpdate();
msgcnt=0;
}
}

 

// 실제 RichEdit에다 데이터 넣기..

void CPG_SendDlg::MsgDisp(const char * pFmt, ...)
{
char msgbuf[1024]="";
va_list vlist;
// 취득된 문자열 가져오기 시작
va_start(vlist, pFmt);
vsprintf(msgbuf, pFmt, vlist);
fflush(NULL);

 

// 끝 - 모든 변수를 읽은 후 정상적인 리턴을 위하여
va_end(vlist);
strcat(msgbuf,"\r\n");
m_msgout.ReplaceSel(msgbuf);
m_msgcount++;
if(m_msgcount > 500) {
m_msgout.SetWindowText("");
m_msgcount=0;
}
}

CreateThread를 만들어 보자구~~~ (20090304)

 

xxx.cpp에 선언

ULONG __stdcall DiagThreadProc(LPVOID pParam);

HANDLE m_hDiagThread;

 

void CPCIe_SimulatorDlg::OnBnClickedDiagstart()

{

if(m_hDiagThread!=NULL) TerminateThread(DiagThreadProc,0);

m_hDiagThread = CreateThread(NULL, 0, DiagThreadProc, this, 0, 0);

}

 

// 쓰레드 시작~~~

ULONG __stdcall DiagThreadProc(LPVOID pParam)
{
CPCIe_xxx* pDlg=(CPCIe_xxx*)pParam; //추가
if (pDlg == NULL || !pDlg->IsKindOf(RUNTIME_CLASS(CPCIe_SimulatorDlg))) return false;

while (TRUE) {

if(m_daigflag == true) break;

// 무한 루핑..

}

return true;
}

 

void CPCIe_SimulatorDlg::OnBnClickedDiagend()
{
m_daigflag=m_bDiagthread=false;
}

 

xxx.h

bool m_daigflag;

DWORD CDllExDlg::SHGetVersionOfFile(LPTSTR szFile, LPTSTR szBuf, LPINT lpiBuf, int iNumOfFields)
{
DWORD dwUseless =0 ;
UINT iBufSize = 0;
VS_FIXEDFILEINFO* lpFFI=NULL;
TCHAR s[MAX_PATH] = {0};

DWORD dwLen = GetFileVersionInfoSize(szFile, &dwUseless);

if(dwLen==0)
{
if(szBuf)
lstrcpy(szBuf, _TEXT("<unknown>"));

return 0;
}

HGLOBAL lpVI = GlobalAlloc(GHND, dwLen);
LPVOID lpvMem = GlobalLock(lpVI);
::GetFileVersionInfo(szFile, NULL, dwLen, lpvMem);
VerQueryValue(lpvMem, _TEXT("\\"),reinterpret_cast<LPVOID*>(&lpFFI), &iBufSize);
DWORD dwVer1 = lpFFI->dwFileVersionMS;
DWORD dwVer2 = lpFFI->dwFileVersionLS;


GlobalUnlock(lpVI);

GlobalFree(lpVI);

//Fill return buffers

if(szBuf!=NULL)
{

wsprintf(s, _TEXT("%d.%d.%d.%d"), HIWORD(dwVer1), LOWORD(dwVer1),HIWORD(dwVer2),LOWORD(dwVer2));
lstrcpy(szBuf, s);

}

if(lpiBuf != NULL)
{

for(int i=0; i<iNumOfFields; i++)
{

if(i==0)
lpiBuf[i] = HIWORD(dwVer1);

if(i==1)
lpiBuf[i] = LOWORD(dwVer1);

if(i==2)
lpiBuf[i] = HIWORD(dwVer2);

if(i==3)
lpiBuf[i] = LOWORD(dwVer2);

}

}

return dwVer1;
}

 

//GetProcAddresses
//Argument1: hLibrary - Handle for the Library Loaded
//Argument2: lpszLibrary - Library to Load
//Argument3: nCount - Number of functions to load
//[Arguments Format]
//Argument4: Function Address - Function address we want to store
//Argument5: Function Name - Name of the function we want
//[Repeat Format]
//
//Returns: FALSE if failure
//Returns: TRUE if successful
BOOL GetProcAddresses( HINSTANCE *hLibrary,
LPCSTR lpszLibrary, INT nCount, ... )
{
va_list va;
va_start( va, nCount );

if ( ( *hLibrary = LoadLibrary( lpszLibrary ) )
!= NULL )
{
FARPROC * lpfProcFunction = NULL;
LPSTR lpszFuncName = NULL;
INT nIdxCount = 0;
while ( nIdxCount < nCount )
{
lpfProcFunction = va_arg( va, FARPROC* );
lpszFuncName = va_arg( va, LPSTR );
if ( ( *lpfProcFunction =
GetProcAddress( *hLibrary,
lpszFuncName ) ) == NULL )
{
lpfProcFunction = NULL;
return FALSE;
}
nIdxCount++;
}
}
else
{
va_end( va );
return FALSE;
}
va_end( va );
return TRUE;
}

 

 

실제 사용예..

#include <windows.h>

typedef int ( WINAPI *MESSAGEBOX )
( HWND , LPCSTR, LPCSTR, DWORD );
typedef int ( WINAPI *MESSAGEBOXEX )
( HWND , LPCSTR, LPCSTR, DWORD , WORD );

void main(void)
{
MESSAGEBOX lpfMsgBox = NULL;
MESSAGEBOXEX lpfMsgBoxEx = NULL;
HINSTANCE hLib;
if(GetProcAddresses( &hLib, "User32.dll", 2,
&lpfMsgBox, "MessageBoxA",
&lpfMsgBoxEx, "MessageBoxExA" ) )
{
lpfMsgBox( 0, "Test1", "Test1", MB_OK );
lpfMsgBoxEx( 0, "Test2", "Test2", MB_OK,
MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ) );
}
if ( hLib != NULL )
FreeLibrary( hLib );
}

 

'프로그래밍 > VC++ 개발 코딩' 카테고리의 다른 글

CreateThread 만들어보자  (0) 2014.01.17
Dll . exe file 정보파일 읽어오기  (0) 2014.01.17
JPG resouce 등록하고 사용하기  (0) 2014.01.17
VC++ PG_SEND  (0) 2014.01.17
동적 라이브러리 만들기  (0) 2014.01.17

JPG resource를 등록하고 사용해 보자.!!

1. GDI+를 초기화한다.

xxxx.cpp 파일 처음부분에 하기와 같이 설정한다.

//////////////////////////////////////////////////////////////////////////
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus")
HINSTANCE g_hInst;
class CGdiPlusStarter
{
private:
ULONG_PTR m_gpToken;

public:
bool m_bSuccess;
CGdiPlusStarter() {
GdiplusStartupInput gpsi;
m_bSuccess=(GdiplusStartup(&m_gpToken,&gpsi,NULL) == Ok);
}
~CGdiPlusStarter() {
GdiplusShutdown(m_gpToken);
}


};

CGdiPlusStarter g_gps;
////////////////////////////////////////////////////////////////////////

2. 제대로 초기와 되었는지 확인한다.

GDI를 사용하는 xxxxx::OnInitDialog() 함수에 하기내용을 추가한다.

////////////////////////////////////////////////////////////////////////

if (g_gps.m_bSuccess == FALSE) {
AfxMessageBox(TEXT("GDI+ 라이브러리를 초기화할 수 없습니다."));
return 0;
}

////////////////////////////////////////////////////////////////////////

3. JPG File을 import 한다.

resource File에 원하는 JPG 파일을 호출하여 등록해둔다.

예를들어, "JPG" IDR_JPG1 이렇게 등록되었다고 가정하자.

4. JPG resource를 열어, Dialog Box에 출력한다.

////////////////////////////////////////////////////////////////////////

CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트

Graphics G(dc);

or Graphics(m_hWnd); 도 가능.


HRSRC hResource = FindResource(g_hInst, MAKEINTRESOURCE(IDR_JPG1),
TEXT("JPG"));
if (!hResource) return;

DWORD imageSize = SizeofResource(g_hInst, hResource);
HGLOBAL hGlobal = LoadResource(g_hInst, hResource);
LPVOID pData = LockResource(hGlobal);

HGLOBAL hBuffer = GlobalAlloc(GMEM_MOVEABLE,imageSize);
LPVOID pBuffer = GlobalLock(hBuffer);
CopyMemory(pBuffer,pData,imageSize);
GlobalUnlock(hBuffer);

IStream *pStream;
HRESULT hr=CreateStreamOnHGlobal(hBuffer,TRUE,&pStream);

Image src_img(pStream);
pStream->Release();
if (src_img.GetLastStatus() != Ok) return;

G.DrawImage(&src_img, 0, 0);

////////////////////////////////////////////////////////////////////////

이렇게 하면 JPG 파일을 열고, Dialog Box에 원하는 resource를 출력해준다.

끝...

참고로, Position 관련하여,

GetWindowRect, GetClientRect, ScreenToClient, ClientToScreen 함수등을 사용하여,

position의 변경을 꾀할수있다.. ^^*

Window Move 및 Command Pipe Connect 방법소개.

1. 프로그래스바 연습

2. cmd pipe 연결연습

3. message 파싱 연습

 

제목은 거창하나 간단한 설명입니다.

아주 세밀한 설명은 다른곳에서 도움 받으시길 원하며, 처음 라이브러리를 접하시는 분을 위해, 그리고 자주 까먹는 저를 위해 이렇게 글로 작성해둡니다.. -.-;;;

라이브러리 사용만 해봤지 한번도 만들어 본적이 없었는데..

갑작스레 회사프로그램을 통채로 라이브러리화시키는 일을 맡아버려서 얕게 나마 알게 되었습니다.

참고로 급조된 지식입니다 -_-;

일단 쉽게 설명하면, 라이브러리란 블랙박스와 같은 형태입니다.

그 안을 들여다 볼수가 없고 export가 허락된 함수나 데이터만 접근할수 있는 형태의 파일을 말합니다.

개발에 용의하고, 모듈화의 적합하기 때문이라고 하지만..

역시 궁극적인 목표는 자신의 기술을 외부에 유출시키지 않는 방법이 아닐까 싶습니다.

예를 들면 mp3를 재생시키는 코딩을 라이브러리화 시켜서 배포하면 누구나 다 mp3재생을 할수 있지만,

그안을 들여다 볼수 없기에 절대 mp3 재생을 위한 코딩이 어떻게 되는지 알수 없습니다.

라이브러리는 정적 라이브러리와 동적 라이브러리가 있습니다.

쉽게 설명하면, 정적 라이브러리는 LIB라는 형태로 프로그램을 만들때 그 lib 파일 자체를 컴파일시에 포함해서 코딩해야합니다.

따라서 프로그램 용량이 커지고, 라이브러리 내용만 수정해야 한다해도 다시 프로그램 전체를 컴파일 해야하는 단점이 있습니다.

동적라이브러리는 DLL형태입니다.

DLL형태는 프로그램을 컴파일할때 없어도 됩니다. 단지 실행할때 dll파일이 함께 있음으로써 사용되어지기에,

프로그램 용량이 적어지고, 라이브러리 내용만 수정되어야 할 일이 있다면 라이브러리만 따로 컴파일하면 되기에 업데이트등에 용이합니다.

이스트소프트사의 알집의 경우 폴더를 살펴보면, 수많은 dll 파일들이 있는데 각각 dll들은 독립된 라이브러리입니다.

만약 알집이 lib를 이용했다면, dll이 없고, 달랑 실행파일 하나와 그외 기타 파일만 존재했을것입니다.

LIB같은 형태는 꼭 숨기고 싶은 라이브러리를 만들때, 혹은 업데이트할 일이 없는 형태일때 만드는것이 좋은것같습니다.

다음은 실질적인 만드는 부분입니다.

저는 vc8 2005로 넘어가게 되서 2005를 기준으로 설명합니다.(사실 vc6과 별 차이없습니다 -.-;)

참고로 라이브러리를 만들때는 라이브러리 프로젝트 외에, 그 라이브러리를 사용하는 프로젝트를 동시에 만들어서,

컴파일하면 라이브러리 먼저 컴파일한뒤, 그 라이브러리를 적용하는 프로그램을 컴파일하게 하면 개발할때 편합니다.

프로젝트를 따로 두면 하나 컴파일하고, 또 그걸 적용해보는 프로그램 컴파일하고, 시간도 시간이지만 엄청 귀찮습니다.

그리고 라이브러리를 import할때는 반드시 경로에 주의해야합니다.

정적 라이브러리 만드는 방법 및, 사용방법

vc6의 경우 프로젝트 첨부할때 보면 맨밑에 Win32 Static Library가 있습니다.

vc8의 경우는 Win32탭에 Win32 프로젝트를 선택하시면 됩니다.

(클릭해서 밑에 설명란 보면, dll 또는 정적 라이브러리를 만드는 프로젝트라고 써있습니다.두개가 2005에서는 합쳐진듯합니다)

선택을 하신뒤 보면, DLL이든 정적라이브러리든 다시 선택할수 있으며, MFC를 정적으로 링크할것이냐도 선택할수 있는데..

이건 사실 별 문제가 아닙니다. 언제든 MFC야 링크하게 바꿀수도 없앨수도 있으니 신경 안쓰셔도 됩니다.

여기서 정적라이브러리를 선택 하시면 프로젝트가 만들어집니다.

솔루션 탐색기를 보시면 stdafx.h와 cpp만 있을것입니다.

이제는 코딩만 하시고, 바깥에서 쓸수있게 export 설정만 하시면 됩니다.

저같은 경우는 코딩의 용이함을 위해 클래스로 만들어서 코딩합니다.

(참고로 굳이 그러실 필요는 없습니다. 코딩스타일은 개인차이고, 또한 알고리즘에 따라 다른거라..)

클래스뷰를 보시면 프로젝트명과 달랑 매크로및 상수만 있는데 여기에 클래스를 추가해줍니다.

클래스명은 반드시 현재 프로젝트명입니다. 그래야 프로젝트명.h와 cpp가 생겨납니다.

클래스로 안만드실 분은 그냥 프로젝트명.cpp만 있어도 됩니다.

그다음 필요한것은 프로젝트명.def 파일을 추가해주어야 합니다. 이 파일은 밖으로 유출시킬 함수를 설정해주는것으로

반드시 필요합니다.(이건 마지막에 하면 됩니다.)

중요한건, export 할수 있는 함수는 전역함수라는것입니다. (정확한건 아닙니다 -.-; 아무래도 급조해서 만들어본거라..)

하지만, 멤버함수야 전역함수에서 가져다 쓸수 있으니 별 문제는 아닙니다

뒤에 특정 클래스의 멤버함수에 접근 하는 간단한 방법도 적어두겠습니다.

일단, 아주 쉬운 예제를 들어보겠습니다

일단 클래스뷰에 프로젝트명 부분에 오른쪽 마우스 클릭하시고 속성을 보시면,

구성속성->일반-> 부분에 정적라이브러리(.Lib)가 선택되어 있는지 확인하셔야 합니다.

그다음,

프로젝트명.h에

void Test();를 선언해준후

cpp에는 (당연히 최상단부에 #include "프로젝트명.h"가 있어야 합니다)

void Test()

{

MessageBox(L"이 메시지박스는 lib내부 함수에서 호출되었습니다", L"", MB_OK);

}

라고 만들었습니다

그후 프로젝트명.def에

EXPORTS

;

Test @1

이라고 코딩합니다.

여기서 test는 밖으로 유출할 함수명이며, @1은 번호입니다.

두번째 유출 함수는 @2, 세번째는 @3 이런식으로 작성해주면 됩니다.

컴파일하면 프로젝트명.lib가 만들어집니다.

그다음 새 프로젝트를 만들어서 테스트를 해보면 됩니다.

새 프로젝트에서 정적라이브러리를 위해 필요한 것은 컴파일된 lib파일과 h파일입니다.

h 파일에는 보통 해당 lib에 접근해서 쓸수 있는 함수가 무엇무엇이 있는지 알려줍니다.

예를 들면 void Test();이런식으로 test 함수를 import할수 있음을 알려줍니다.

(h파일이 반드시 필요한지는 잘 모르겠습니다 한번도 빼본적이 없어서 -_-;)

보통 lib와 같이 포함되는 h파일 작성은 위와 같은 코딩이였다면,

void Test(); 이것 하나만으로 충분합니다. lib 안에 import 할수 없는 함수라면 적을 필요없습니다.

즉, lib 프로젝트할때 쓴 lib프로젝트명.h에서 쓸데없는거(import불가능한것들) 다 지우고 가져다가 쓰시면 됩니다.

위에 예제를 계속 이어간다면,

프로젝트 속성에 구성속성->라이브러리관리자-> 일반에 보시면 추가종속성이 있습니다.

그곳에 반드시 lib프로젝트명.lib를 추가해주세요

새프로젝트명.h에는 #include "lib프로젝트명.h" 선언해주시구요

그다음에는 그냥 Test();

호출만으로 lib안에 Test()가 호출됨을 알수 있습니다.

동적 라이브러리 만드는 방법, 및 사용방법

vc6의 경우 프로젝트 첨부할때 보면 맨밑에 Win32 Dinamic-Link Library가 있습니다.

vc8의 경우는 Win32탭에 Win32 프로젝트를 선택하시면 됩니다. (정적라이브러리와 동일합니다)

역시 2005를 기준으로 하며, 위에 설명이 있으니 간단하게만 설명하겠습니다.(2005나 vc6이나 사실 별차이 없습니다)

프로젝트 속성을 보시면, 구성속성->일반-> 부분에 동적라이브러리(.Dll)로 바꾸어주셔야 합니다.

정적라이브러리와 마찬가지로, 해당프로젝트명.cpp가 기본 base입니다.

해당프로젝트명.h는 역시 선택사항입니다.

다른점은 밖으로 export할 전역 함수들의 선언인데..

동적 라이브러리는 extern "C" __declspec(dllexport)를 앞에 붙여줍니다.

예를 들어 프로젝트명과동일한 클래스를 추가한후,

프로젝트명.h에는

extern "C" __declspec(dllexport) void Test();

라고 선언해주고,

프로젝트명.cpp에는

__declspec(dllexport) void Test()

{

MessageBox(L"이 메시지박스는 lib내부 함수에서 호출되었습니다", L"", MB_OK);

}

이렇게 함수를 만들어줍니다.

정적라이브러리와 마찬가지로 전역함수이며,

특정 클래스에 접근하는 방식 또한 뒤에 쓴것처럼 하시면 됩니다.

문제는 def파일인데..

만들지 않아도 상관없습니다

(밑에 EXPORT 하는 방법은 따로 있으나, 지금 이대로 해도 상관없습니다.)

이제 다른 프로젝트에서 불러오는 일만 남았는데..

불러오는 방식은 implict와 explicit 두가지 방법이 있습니다.

두가지 방법의 차이는

implicit 링킹은 프로그램이 시작되면서 해당 dll을 바로 로드 하는 방식으로, h파일, lib 파일 모두 필요합니다.

처음부터 제가 dll을 만들기 시작한 업데이트성의 용이를 위해서 h파일과 lib파일은 없어야할 존재이기에 이 방법은 해보지 않았습니다.

explicit 링킹은 단지 dll 파일 하나만으로 호출 가능한 방법입니다.

다음은 explicit 방법을 사용해서 dll만으로 import 하는 방법입니다.

dll을 사용하게 될 새 프로젝트를 하나 만드시고, lib와는 다르게 프로젝트의 추가종속성에 dll 파일을 넣으시지 않아도 됩니다.

(확실하진 않지만 아마 넣으면 에러가 나오던가 그랬던걸로 기억합니다. -_-;;; 확실한건 안넣으셔도 된다는것..)

필요한것은 단지 dll을 호출하는것입니다.

호출할때는 해당 dll을 로드하고 함수를 사용하면 됩니다.

예)

HINSTANCE hDll; //dll파일을 로드할 인스턴스핸들입니다.

hDll = LoadLibrary("해당파일.dll"); //로드합니다.

typedef void (*TestFunc)(); //불러올 Test파일이 어떤 형식인지 알고 반드시 같은 형식으로 typedef로 설정합니다.

//혹시 test함수가 int test(int num);이라면 typedef int (*TestFunc)(int num);으로 해주어야합니다.

TestFunc Test; //test()를 import시키기 위한 설정입니다.

Test = (TestFunc)GetProcAddress(hDll,"Test"); //test함수를 얻어옵니다. GetProcAddress의 두번째인자는 해당함수명입니다.

Test(); //import한 함수를 실행합니다.(dll내의 함수가 직접 호출)위와같은 dll을 만들었다면 메시지박스가 호출되어질것입니다

FreeLibrary(hDll); //사용후에는 반드시 닫아주셔야 합니다

가장 중요한것은..loadLibrary해줄때 경로가 틀리면 에러가 난다는 점입니다.

제가 배운 서적에는 hDll == NULL 이라면 dll이 로드 안된거라고 나왔는데..

제가 해보니 로드 안되었는데도 NULL이 아니라서 에러때문에 고생했습니다 -_-;; 저는 2005에서 해서 다른건지는 잘 모르겠습니다.

여기까지만 하셔도 dll의 기능은 충분히 수행할수 있습니다

다음은 데이터변수도 공유방법과, EXPORT도 설정방법입니다. (저는 사용하지 않았습니다.)

공유 데이터 정의할때는

#pragma data_seg("SHARDATA")
int 공유할 변수;
#pragma data_seg()

라고 해주고,

def 파일에

SECTIONS
SHARDATA Read Write Shared

를 추가합니다.

EXPORT 방법은 EXPORT할 함수 선언은

void CALLBACK Test();

라고 선언해주고

def에는

EXPORT

Test @1

로 해줍니다. 역시 @1는 함수번호로 그다음 함수는 @2 등으로 순차적으로 부여해줍니다.

정적 라이브러리 -> 동적라이브러리 변경하는 방법

(반대 경우도 마찬가지)

저는 MFC DLL 프로젝트로 만들어 보지 않고 Win32 DLL프로젝트나 LIB으로만 만들어 봐서 MFC DLL 프로젝트에서 바꾸는 법은

잘모르겠습니다 -.-; 일단 해보지 않은거라...

그치만, Win32에서는 간단합니다.

위에 보시면 아시겠지만, 정적라이브러리와 동적 라이브러리 만들때 차이는 export 시키는 함수 선언등 약간의 차이뿐이라..

그냥 위에 글 보시면서 함수 선언부분이랑 프로젝트 속성->구성속성->일반 부분 바꿔주시고, def부분도 바꾸시면 됩니다.

저도 처음에 lib로 만들었다가 dll로 필요했다는걸 알고 lib 상태에서 바로 dll로 바꿔 만들었습니다.

그리고 그걸 바꿔주는 프로그램도 있다 그러는데.. 큰 차이가 없어서 저는 그냥 코딩으로 바꿔주었습니다.

MFC 링크 없애는 법, 추가하는 법

초반에 프로젝트 생성할때, mfc 링크를 선택하는데, 이부분은 단지 프로젝트속성에서 mfc 링크로 바꾼다고 어떻게 되는 부분이 아닙니다. 그러나 MFC 링크는 없애는 법과 추가하는 법이 모두 간단합니다.

여기에 코딩하면 좀 길어져서 아주 쉬운 방법만 알려드리겠습니다.

처음 라이브러리 프로젝트 만들때 MFC 링크를 선택하느냐 안하느냐에 따라 stdafx.h의 내용이 달라집니다.

즉, 아무 프로젝트나 새로 만들어서 mfc 링크를 해보고, 안해보고 두개 만들어보면 됩니다.

mfc를 없애고 싶으면, 추가 안한 프로젝트의 stdafx.h 내용으로 바꾸면 되고, 추가하고 싶을때는 그 반대로 하면 됩니다.

전역함수에서 특정 클래스의 멤버함수에 접근 하는 방법

저는 클래스의 멤버함수를 직접 export 시킬수 있는지는 솔직히 잘 모르겠습니다.

그러나 전역함수에서 언제든 연결할수 있으니 별 문제는 없는것 같습니다.

간단한 라이브러리라면 모를까..

보통 클래스도 많이 들어간 덩치 있는 라이브러리를 만든다면 반드시 클래스에 접근을 해야합니다.

뭐 예를 들어 전역함수 몇개를 export 시켜두고 그 전역함수를 호출하면 그 전역함수내에서 클래스 멤버함수나 쓰레드 전역함수등에 접근 하는 방식을 사용하면 됩니다.

방법은 간단합니다.

라이브러리를 만드실때 원하는 클래스가 CTest라는 클래스라면,

cpp 파일에 전역변수로 CTest g_Test;라고 선언해줍니다

전역 함수내에서 CTest클래스에 접근할때

g_Test.접근원하는멤버변수나 함수;를 사용하시면 됩니다.

그리고, 라이브러리 외에 보통 프로젝트에서 전역 함수네서 변수를 쓰는 방법은 약간 다릅니다

CTest라는 클래스의 멤버에 접근하고 싶다면

CTest g_pTest;라고 포인터 전역변수를 설정하고,

해당 클래스 생성자 부분에 g_pTest = this;라고 해준후

전역함수내에서 g_pTest->원하는멤버;

이런식으로 상요해주시면 됩니다.

혹시 모르시는 분을 위해..

참고로 생성자는 생성될때 제일먼저 호출되는 함수로

C클래스명::C클래스명(void) //생성자함수
{

g_pTest = this;//이런식으로 들어가면 됩니다.
}

이런식으로 되어있습니다. (클래스 추가를 통해 만들면 자동으로 만들어집니다.)

예전에는 이런 방법을 몰라서 전역함수로 핸들을 직접 넘겨주고 그랬는데 --; 알고보니 참 간단하더군요

1. 메모리할당
우리가 흔히쓰는 선언은 정적 선언이라고 합니다.
즉, 메모리의 총량이 정해져 있다는 것입니다.
정적 선언으로 인해 지정된 변수는 Stack 이라는 메모리공간에 저장됩니다.
※ 참고 : 블럭이 시작 될 때도 stack 에 메모리를 할당합니다.
이를 전문용어로 Activation Recorde라고 합니다.

이에 비해 아래에 나올 동적 선언으로 인해 지정된 변수는
Heap 이라는 메모리에 저장됩니다.

그럼 이젠 동적 할당을 알아봅시다.

2. 동적 할당
동적 할당은 말 그대로 용량이 정해져 있지 않고 변화하는 것을 이야기 합니다.
동적 할당은 다음의 경우에 사용합니다.
1) 필요한 크기를 미리 알수 없는 경우
2) 실제로 필요성 여부를 모르는 메모리를 부여할 때
3) stack size에 한계가 있으므로
이 3가지의 이유에 해당될 때 동적 할당을 사용하게 됩니다.
동적 할당 명령어로는 malloc(), calloc(), realloc() 이 있습니다.
그리고 헤더 파일(#include)로 stdlib.h 를 첨부해주어야 됩니다.
또한, 동적 할당은 Heap메모리에 랜덤으로 부여 되므로 포인터처럼 주소를 이용하여
조작을 해야 됩니다. 이에 따라 동적 할당할 변수는 포인터로 지정
해줍니다.

3. malloc()
흔히 엠알록 또는 멀록이라고 하는 명령어로 가장 많이 사용되는 동적 할당 선언서 입니다.
int *ip;
char *c;
ip = (int *)malloc(sizeof(int)) ;
c = (char *)malloc(strlen("hello")+1);


변수이름 = (형식 *)malloc(크기)

이런 형식의 문법을 가지고 있습니다.
포인터형식의 변수를 선언해주고, 그 변수에 동적할당을 하는 것입니다.
위의 예는 인티져크기로 할당된 ip와 hello를 넣을 만큼의 크기가 되는 c를 동적 할당으로
만들어 낸 것입니다. c = (char *)malloc(strlen("hello")+1)에서 +1은 꼭 지켜 주십시요.
Null(\0)가 들어갈 자리 입니다.

4. calloc()
calloc은 동적 할당의 크기뿐만아니라 그것을 만들어낼 개수를 지정해줄수 있습니다.
int *ip;
ip = (int *)calloc(5,sizeof(int));

변수이름 = (형식 *)calloc(개수,크기)

이런 형식의 문법을 가지고 있습니다.
malloc과 똑같이 포인터형식의 변수를 선언해주고, 그 변수에 동적할당을 하는 것입니다.

특징은 그 개수를 지정하여 배열처럼 사용이 가능한 것입니다.
위의 예는 인티져크기로 할당된 ip를 5개 복제하는 것입니다.

5. realloc()
realloc은 동적 할당된 것을 다시 할당하는 것입니다.
int *ip;
ip = (int *)malloc(sizeof(int));
ip = realloc(ip,sizeof(int)*2);

변수이름 = realloc( 없엘 변수, 크기)

이런 형식의 문법을 가지고 있습니다.
위의 예를 들어 설명하면 인티져크기로 선언된 ip를 free시켜 ip에 인티져크기의 두배가
되는 메모리를 할당 하는 것입니다.
free는 아래에서 설명 하도록 하겠습니다.
만약 없엘 변수가 없다면, malloc과 똑같은 역할을 하고,
크기가 없다면, free와 같은 역할을 합니다.

6. free()
int *ip;
ip = (int *)malloc(sizeof(int));
free(ip);

free(변수이름)

동적 할당된 메모리는 프로그램에서 다시 지정하지 않는 이상
프로그램이 끝날 때까지 남아있습니다.
쓸 때없이 할당된 메모리가 늘어나면 프로그램이 느려지며, 일명 랙!! 이 걸립니다.
이를 메모리가 센다고 흔히들 말합니다.
이를 방지하기 위해서는 free를 사용하여 할당된 메모리를 놓아주면됩니다.
위의 예는 ip에 인티져크기만큼 동적할당을 하고 난 뒤에 ip를 free를 이용하여
ip가 가지고 있던 메모리를 놓아주는 것입니다.

+ Recent posts