설명 #

"함수포인터"는 C언어에서 자주 쓰이는 기본 용법중 하나입니다. 정의는 다음과 같습니다.
선언된 함수가 저장된 메모리 번지값을 담고 있는 포인터 변수
하지만 이것을 왜 보통의 포인터와는 달리 특별취급하냐면 다음과 같은 이유 때문입니다.
  1. 일반 포인터 변수와는 조금 다르게 보이는 문법으로 선언됩니다. 예를 들어 함수 포인터 변수는 다음과 같이 선언합니다. (functionPtr이 포인터 변수명이 됩니다)
    void (*functionPtr)(const char *s_)
    
  2. 함수포인터는 실행부분을 가리키는 포인터 변수인탓에 () 연산자를 사용할 수 있습니다. 즉, 위의 functionPtr은 아래와 같이 실행가능합니다.
    functionPtr("바보나라~")
    

주로 함수포인터는 콜백(callback)을 구현하는데 사용됩니다. 어떤 라이브러리를 제작할 때 개발자가 어떤 "경우"에 대한 반응을 함수로 작성하고 이를 다시 라이브러리에서 호출하도록 작성하고자 할 때, 개발자가 작성한 함수의 포인터를 넘겨받아 실행하도록 하면 아주 유용할 때가 많습니다. (대표적인 예가 win32 api에서 윈도우 프로시져를 WNDCLASS의 lpfnWndProc맴버에 등록하는 부분을 들 수 있습니다) 즉, 함수를 마치 변수와 같이 취급하는 것이 가능해집니다.

예제 #

아래 예제는 함수포인터를 활용한 간단한 예제입니다.
#include <stdio.h>

void testout1(const char *s) {
  printf("시험출력1:%s\n", s);
}

void testout2(const char *s) {
  printf("시험출력2:%s\n", s);
}

// 함수포인터 변수
void (*funcPtr)(const char *s);

int main() {
  // 함수포인터를 testout1, testout2로 각각 대입해보고 실행해본다.
  funcPtr = testout1;
  funcPtr("테스트");
  funcPtr = testout2;
  funcPtr("테스트");
}

실행결과는 아래와 같습니다.
시험출력1:테스트 시험출력2:테스트
main()안에서는 funcPtr만 실행했지만 마치 testout1, testout2를 각각 실행한 것과 같은 효과가 있음을 알 수 있습니다.

typedef 거는 법 #

함수포인터를 어떤 포인터 변수로서 활용하고 싶을 때 typedef를 활용하면 매우 편리합니다. 실제로 win32 API에서는 윈도우 프로시저 함수포인터형으로 WNDPROC라는 타입이 있습니다. (이부분을 보면 어느정도 사용법에 대한 느낌이 올겁니다) winuser.h 헤더화일에서 검색해보면 다음과 같이 선언되어있습니다.
typedef LRESULT(CALLBACK *WNDPROC)(HWND,UINT,WPARAM,LPARAM);
실제로 사용될 때에는 다음과 같이 사용됩니다.
LRESULT CALLBACK winproc1(HWND,UINT,WPARAM,LPARAM) { }; ... WNDPROC winprocPtr = winproc1; ...
꽤 유용한 문법이니 알아두시면 좋습니다.

주의사항 #

함수포인터는 알아두면 상당히 유용한 기법이지만 사용시에는 다음과 같은 부분을 주의해야합니다.
  1. 대입되지 않은 (NULL값상태의) 함수포인터를 실행하지 않도록 주의해야합니다. 초기화를 항상 NULL로 해두고 실행전에 검사하는 것도 좋은 방법입니다.
  2. "같은 함수 포인터 타입"이라는 것을 증명하려면, 반환값, 매개변수의 타입 및 개수가 모두 일치해야합니다. 보통 하나라도 다른 함수포인터값을 대입하면 컴파일시 오류가 나게 됩니다.


출처 : http://www.redwiki.net/wiki/wiki.php/%C7%D4%BC%F6%C6%F7%C0%CE%C5%CD

출처 : http://blog.naver.com/gml81/40037809685

MapWindowPoints : CWnd의 좌표계로부터 다른 윈도우의 좌표계로 지정된 점들을 매핑시 킨다.
ClientToSreen : 클라이언트 좌표계를 화면 좌표계로 변환한다.
ScreenToClient : 화면 좌표계를 클라이언트 좌표계로 변환한다. 
-----------------------------------------------------------------------------

OnPrepareDC()에서

    dc.SetMapMode(MM_ISOTROPIC);

    dc.SetWindowExt(1000,1000);

    dc.SetViewportExt(2000,2000);

      CClientDC dc (this);
     OnPrepareDC (&dc);
     dc.DPtoLP (&point);
point가 마우스 좌표라면 논리 좌표로 변환해 주는 코드입니다.

 ----------------------------------------------------------------------------------

jpg 이미지가 255*255 픽셀 크기인데요...
출력을하면은 255*255 크기가 아니고 적게 출력이 되는데.
무슨 이유입니까??

좌표계가 MM_TEXT로 설정되어 있어서 그럴겁니다

 MM_TEXT 좌표계는 하나의 픽셀이 기준이 됩니다
질문하셨다 시피 jpg 이미지가 255*255 크기라면   
좀 픽셀이 큰 모니터에서는 이미지가 더 크게 나오겠죠?

출력을 할때도 마찬가지로
프린터 장치의 dpi라고 하죠 1인치 사각형안에 얼마나 많은 점들을 찍을수 있느냐 하는 건데
(보통 300dpi 뭐 이런 얘기 많이 들어보셨을 겁니다)
이 프린터의 dpi에 따라 이미지 사진이 더 크게나올수도 있고 작게나올수도 있는겁니다

왜냐하면 기준이 픽셀이기 때문이죠 

그럼 화면과 출력물의 크기가 같아지기 위해서는 어떻게 해야하느냐 하면
MM_LOMETRIC같은 좌표계를 쓰시는 겁니다

MM_LOMETRIC은 자표계 기준이 0.1미리 입니다
따라서 MM_LOMETRIC좌표계 기준으로 1000*1000의 그림은
화면에서나 출력에서나 10cm * 10cm로 동일하게 출력되는 것이죠

쉽게 말씀드리면

 SetMapMode() 함수를 이용해서 좌표계를 바꿔주라는 이야기 입니다 ^^
SetMapMode(hPrinterDC, MM_LOMETRIC); // 이런식으로요

물론 출력하실때 좌표계가 바뀌었으니 출력될 좌표는 신경쓰셔야 겠죠 ^^
참고로 MM_LOMETRIC은 MM_TEXT와는 달리

y축이 아래로 가면 - 값 입니다

덧붙이자면

BOOL DPtoLP() // 디바이스 좌표를 로직좌표계로 바꿔주는 함수와 그 반대 함수들이 존재하니 참고 하시구요

 -----------------------------------------------------------------------

 DPtoLP는 함수 이름 대로 디바이스 좌표를 논리적 좌표로 변경해주는 함수입니다...
 디바이스 좌표는 화면의 한 Pixel, 프린터의 한 Dot를 뜻합니다.
논리적 좌표는 논리적으로 단위를 정한 좌표입니다.(예로 10cm단위로 1, 2, 3...)
 일반적으로 GetDC()를 하게 되면 리턴되는 DC는 MM_TEXT 모드가 됩니다.
MM_TEXT는 디바이스 좌표와 논리 좌표가 1:1 대응(화면의 한 점이 1이 됩니다.)됩니다.
결국 DPtoLP를 해도 값의 변화가 없겠죠...

하지만 map mode를 MM_HIMETRIC으로 변경했다고 가정하면 논리적 좌표 1은
0.01mm를 나타내기 때문에 화면의 한 pixel은 화면 DPI에 따라 1이 아닌 다른 논리적 값이 됩니다...

[출처] [MFC] 좌표계|작성자 영희

이클립스에서 시그윈의 gcc를 써서 프로그램을 개발하는건
간접적으로는 윈도 환경에서 리눅스 프로그래밍을 개발하는것과 비슷한 효과를 줍니다.

물론 윈도우 환경하에선 Visual Studio 에서 프로그래밍을 하는것이 가장 효과적이라 할수 있지만
세상 모든 프로그램이 M$의 윈도우에 도는 프로그램만 있는것이 아니니

좀더 넓게는 무료 OS, 리눅스 난잡한 버젼들이 퍼져 있기때문에,
.. 예를들어 PMP나.. PSP나... NDS나..  모바일 해킹 디버깅툴이라던가
대부분 리눅스 gcc등을 제공하죠..

즉 리눅스 프로그래밍을 해야 하고..
리눅스 프로그래밍이면 vi와 울트라 에디트라 생각합니다... (관련 :  http://rosagigantea.tistory.com/267)
물론 vi가 좋긴 한데... putty 작업이 아니라면 이클립스도 꽤 좋다고 해서
이클립스로 C언어 컴파일 하는 방법을 찾게 되었습니다.
(이게 아니면.. 코드 블락이라는 vc나 이클립스에 비해 상당히 프로그래머를 피곤하게 햐는 IDE를 써야 하기에;;)

서문을 대략... 이만 줄이고
이후 사진 설명입니다.

음.. 이건.. 이클립스 3.3 버젼으로 한겁니다. (2008.7.9일 기준 최신 이클립스)
뭔가.. http://www.eclipse.org/ 에서 language IDE 의 C쪽을 받아서 설치하는분도 계시는거 같지만..
뭐가 뭔지 잘 모르겠고... 걍 간단하게 기존 Java 이클립스에서 플러그인 설치 하는 방법을 설명 합니다.

그리고.. 이 이전에 시그윈이 설치되있어야 한다는 전재가 깔려 있습니다. 설치가 안되어있다면
http://www.cygwin.com/ 에서 시그윈을 설치 한뒤
윈도우 제어판 -> 시스템 속성 -> 고급 -> 환경변수 -> 변수의 Path 부분 맨 앞에 C:\cygwin\bin;C:\cygwin\usr\include; 을 추가해 줍니다.

<버젼 확인>

사용자 삽입 이미지

1. help-> software update -> find and install 을 합니다.
사용자 삽입 이미지

2. Search for new features to install
사용자 삽입 이미지

3. Europa Discovery Site 선택후 finsh
사용자 삽입 이미지

4. 플러그인 다운로드할 사이트를 찾습니다. 저기 카이스트를 선택해 줍니다.
사용자 삽입 이미지

5. 뭔가 마구 떴습니다.
 하지만 우리가 설치할 플러그인은 CDT 즉.. C/C++ Development Tools 입니다. 해당부분만 체크 합니다.
 Ruby 나... UML 관련 플러그인도 있으나... 현재는 CDT에 집중합니다.
사용자 삽입 이미지

6. 라이센스 동의를 구하는 페이지입니다.
사용자 삽입 이미지

7. 이제 설치할껏들 목록이 뜹니다. finish 를 눌러줍시다.
사용자 삽입 이미지

8. 뭔가 다운로드중~~
사용자 삽입 이미지

9. 헐 이것은 뭘까... 그냥 이전 버젼이 있는거 같은데 덮어쓸까요 정도로 보시면 됩니다..
  (증명서 동의 같은겁니다..)
  Install All 해줍시다.
사용자 삽입 이미지

10. 다 설치후 재시작 할꺼냐고 묻습니다. 당연히 재시작 합시다.
  한참뒤 안뜨면 윈도우 + D 키를 눌러서 워크스페이스를 이클립스 로고(작업표시줄에 안뜰때도 있습니다.)를 컨트롤 하던지.. 걍 다시 기동 시킵니다.
사용자 삽입 이미지

11. 기억상 보았던 맨 처음 OverView 와 동떨어진 디자인이 뜹니다.. 이렇게 나오면 반은 성공!
 상단 가운데쯤의 화살표를 눌러 워크 스페이스로 갑시다.
사용자 삽입 이미지

12. 별로 변한게 없는거 같습니다.
  정말 그런지 새 프로젝트를 만들어 봅시다.
  그냥하면 Java 프로젝트가 뜨니.. 맨 아래 other 를 눌러 들어갑니다.
사용자 삽입 이미지

13. 음.. 목표대로 C 프로젝트를 선택해서 컴파일 해봅니다.
사용자 삽입 이미지

14. 제일 고전적인 추억의 코딩... hello world 를 만듭니다.
   이클립스 하던식으로 프로젝트 이름만 적어주고 finish 클릭 
사용자 삽입 이미지

15. 음... 기본 소스가 나옵니다...
   이 예제는 puts 로 나오는군요..  printf로 교체하셔도 무방하겠죠..
   일단 컴파일 Ctrl + F11을 눌러봅니다.
사용자 삽입 이미지

16. 음.. 문제가 생기는군요..
   문제를 보아하니 cygwin1.dll 이 없답니다.
사용자 삽입 이미지

17. 뭐 이럴경우.. cygwin1.dll 파일이 없다는거니까....... 저 파일을 프로젝트 소스안에 복사를 하던지..
  걍 간단하게 windows\system32 방에 복사를 합니다.
  (하지만 배포할때  저 파일들을 같이 배포하셔야 하겠죠..)
  참고로 cygwin1.dll 파일은 cygwin\bin 디렉토리 안에 있습니다.
사용자 삽입 이미지
사용자 삽입 이미지

18. 음.. 복사도 했고 이젠 되는지 다시 컴파일 해봅니다.
  잘되는군요..
사용자 삽입 이미지


이후 약간의 팁... 굳이 안해도 됩니다.
Windows -> Preferences... 에 들어갑니다.
사용자 삽입 이미지

C/C++ -> New CDT project wizard -> Makefile Project -> Binary parsers 의 아래것들을 체크합니다.
사용자 삽입 이미지

erroe parsers 는 모두 체크 되있구요...
사용자 삽입 이미지

behaviour -> auto build 를 체크하면.. 리소스 저장할때마다 자동 디버깅을 해준다고 하네요..
사용자 삽입 이미지

뭔가 제가 못찾은거라서 그런건지 몰라도
이클립스에서 MinGW을 사용하여 컴파일 하는방법은 많지만
Cygwin을 사용하여 컴파일 셋팅하는건 그다지 없더군요....
(아니 원래 간단한거라 아무도 문제 제기하지 않은건가.. orz)

출처 : http://shinnara.tistory.com/204

===================================================================================================

 조금 전에 스텔라리움이라는 오픈소스 천문 프로그램에 대한 소개글을 올렸습니다. 글에 써 있듯이 한글 문제로 인해 실행이 안되는 현상이 보였습니다. 그래서 오픈 소스인 만큼 소스를 받아서 고쳐볼까하는 생각을 하게 되었습니다. 평소에 Java 를 주된 개발 언어로 사용하다보니 C 와 관련된 툴은 거의 사용하지 않습니다. 이상하게도 저랑 C는, 특히 Visual C++ 은 별로 친하지 않더군요. 회사나 학교에서도 거의 Java 만 사용합니다.

 그런데 요즘 들어 오픈소스 커뮤니티에 대해 많은 관심을 가지게 되면서 C의 필요성을 크게 느끼고 있습니다. 그래서 예전 기억을 살려 다시금 C를 하려고 하는데, 그렇다고 Visual C++ 툴을 이용하고 싶지는 않았습니다. 평소에 자주 이용하는 Eclipse 를 개발툴로 정하고, Eclipse 에서 어떻게 하면 C를 사용할 수 있는 지를 알아보았습니다.

 Eclipse 의 홈페이지에 가보니 C 개발을 위한 CDT 라는 환경을 지원합니다. 특별히 다운받기 보다는 Eclipse 의 업데이트 과정을 통해서 설치를 할 수 가 있는데, 오늘자로볼 때 최신 CDT 버전은 4.0.1 입니다. (관련 페이지는 이곳 ) 그런데 4.0.x 는 Eclipse 3.3 이상에서 실행하도록 되어 있습니다. 제가 그동안 쓰고 있던 Eclipse 의 버전이 3.2 였던 관계로 이클립스를 다시 설치해야 했습니다. 오늘을 기준으로 최신 버전은 3.3.1.1 입니다.

설치를 하고나서, Eclipse Update 를 통해 CDT 를 설치합니다.  설치를 끝내면 다시 시작하라는 메시지가 나옵니다. Eclipse 를 다시 시작해 보니 다음과 같은 모습입니다.


사용자 삽입 이미지

사용자 삽입 이미지

Welcome 화면에 C/C++ Develpment 라는 항목이 생겨있네요.  File 메뉴에서도 C/C++ 을, Perspective 에서도 C/C++ 을 설정할 수 있습니다.

제대로 설치가 되었느지를 확인해보기 위해 helloworld.c 를 만들어보았습니다.

#include <stdio.h>

void main()
{
    printf("HelloWorld");
}

하도 오랫동안 C를 안써봤더니 이게 맞는 소스인지는 모르겠습니다. 별다른 메시지가 나타나지 않길래 Run 을 해보았습니다. 그런데 이게 왠일입니까? 다음과 같은 에러를 나타내며 실행이 안됩니다.

사용자 삽입 이미지

"Launch failed no binaries"
binary 가 없다면서 실행이 안되는다는 것입니다. 도대체 무슨 소린지... 그래서 CDT Help 를 찾아보았습니다.

C/C++ Development User Guide 의 가장 처음 문서 "Before you begin" 을 보니 다음과 같은 내용이 있습니다.

Windows

For windows, MinGW, and Cygwin are the two main choices for acquiring the GNU toolchain:

  • Cygwin is a port of the Linux environment to Windows. It provides a compatibility layer in a set of DLLs. These DLLs are GPL licensed, making any code that links to them also subject to the GPL. Cygwin, however, does provide the fullest implementation of the GNU toolchain by supporting the GNU libc C runtime library.


  • MinGW is a port of the GNU toolchain to the Windows platform. The biggest difference over Cygwin is that MinGW uses the Windows C runtime libraries (mscvrt) instead of GNU's libc. As a result, a compatibility layer is not required, thus avoiding the GPL issues with Cygwin. There are differences, though, between the Windows and GNU C runtime libraries that will make writing portable applications more difficult.

    However, MinGW provides the best integration support with the CDT due to it's direct support for the Windows environment.


    The following are instructions and links on how to install the current version of MinGW. Note that these links may become inaccurate over time as new versions of MinGW components are introduced. Please check the MinGW File Release section for the latest versions.


    1. Download and run the MinGW setup program, MinGW-5.1.3.exe.
    2. Select download and install the MinGW base tools and the g++ compiler. You may select the Current or Candidate version of these tools. You may also install any of the other available compilers as well.

      Do not install the MinGW Make feature as the MSYS version of make from step 5 is a more complete implementation of make.

    3. The MinGW setup program currently does not install the gdb debugger. To install the debugger, download the file from the following location: gdb-6.6.tar.bz2
    4. Extract the contents of the file gdb-6.6.tar.bz2 to the same location where you installed MinGW.
    5. If you want to use Makefile projects, download and run the setup program from the following location: MSYS-1.0.10.exe. MSYS provides an implementation of make and related command line tools. This is not required for other types of projects with the MinGW toolchain, which use CDT's internal build tools to perform the build

Windows 에서 CDT를 사용하기 위해서는 cygwin 이나 MinGW 가 필요하다는 것입니다. 그래서 MinGW 를 설치하였습니다.

MinGW 5.1.3 다운로드

저는 Automated MinGW Installer를 다운받아 실행했습니다. 설치를 하게되면 설치할 Component 를 선택하는 메뉴가 나오는데, 위의 설명에서와 같이 MinGW basetools 과 g++ compiler 를 선택합니다. 위의 설명에 보면 절대로 MinGW Make는 설치하지 말라고 나옵니다.

사용자 삽입 이미지

설치할 디렉토리를 선택하면 인스톨러가 설치 파일을 다운로드하여 설치를 해줍니다.

설치가 끝나면 디버거를 설치하는데요, 여기 에서 gdb-6.6.tar.bz2 를 다운받아 MinGW 의 설치디렉토리에 압축을 풉니다. 저의 경우, 몇몇 화일이 이미 존재한다고 나오길래 덮어썼습니다. ^^

Makefile 을 이용하기 위해서는 MSYS 를 설치합니다. 설치파일은 MSYS-1.0.10.exe

기본 설치가 끝나면 post-install 과정에서 mingw 의 설치 디렉토리를 d:/mingw 와 같은 형식으로 입력해줍니다.

그리고 나서 Eclipse 를 새로 시작하여 새 프로젝트를 생성해봅니다.

C Project 를 시작하려하니 오른쪽 toolchain 에 MinGW GCC 라는 것이 보입니다.

사용자 삽입 이미지

제대로 동작하는 지를 알아보기 위해 Hello World ANSI C Project 를 선택합니다.

Project Wizard 가 끝나고 나면 소스 코드를 볼 수 있는데 다음과 같이 바꿔보았습니다.

/*
 ============================================================================
 Name        : helloworld.c
 Author      : Shinnara
 Version     :
 Copyright   : It's Free
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    puts("Hello World! I'm Shinnara"); /* prints !!!Hello World!!! */
    return EXIT_SUCCESS;
}


Run 을 해보니 역시 제대로 동작하는 군요. 블로그에 올리기위해 이클립스를 프레임을 잔뜩 줄여봤는데 모습이 이상하군요. 어쨌든 제대로 동작하는 것을 확인할 수 있습니다.

사용자 삽입 이미지


이제 개발환경이 갖추어졌으니, 멋지게 개발하는 일만 남았네요. Eclipse, 참 좋은 개발 환경입니다 ^^

===================================================================================================

음.. 참고로 이클립스는 자바용 이클립스로 하면되고, C IDE 이클립스를 사용하면 설정이 안먹히는거 같다.
굳이.. Visual Studio 가 있는데 이클립스로 하려는 이유는...
모바일 게임기 계열이 리눅스프로그래밍을 많이 하는데, 리눅스 프로그래밍에선 vi 아니면 이클립스 for linux 만 있지... VS는 없기 때문.. orz
제가 리눅스 프로그래밍에 발을 들이게 된것은
원래 운영체제 수업때문인것도 있었지만.. 그땐 vi보단 x-window 상의 메모장 프로그래밍이라
당시 visual studio에 익숙했던 저에겐 무리였습니다..

그러다가 이번 게임 서버 프로그래밍 과목에서 프로그래밍을
putty 를 써서 원격 접속 프로그래밍을 하라고 하셔서..

정말 오랫만에 보는 dos 비슷한 모드에서의 난생처음 써보는 vi로 작업을 했습니다.

<putty 작업>
사용자 삽입 이미지
딱 봐도 생 노가다 입니다. (지운건 서버  ip)
옆엔 vi 로 코딩하고
다른 창으로 make 및 프로그램 테스트...  orz

그러던 도중 알아넨 울트라 에디터로 하는 방법...
아래 그림을 봐주세요 >_<..
사용자 삽입 이미지

솔직히 vi보다는 전 비주얼적으로 하는게 더 났더군요.
그래서 이걸 셋팅 하는 방법을 캡쳐해 보았습니다.

1. 우선 울트라 에딧을 설치한뒤, 환경설정에서 시스템 관리자 or 프로그래머를 선택해 줍니다.
사용자 삽입 이미지

2. 우선 시스템 관리자로 선택하면 아래에 ssh 창이 뜹니다. 거기서 계정을 눌러줍니다.
   그리고 관련 셋팅을 합니다
사용자 삽입 이미지

3. 창까지 적절하게 밀고, 연결을 해봅니다. 연결이 안되면 프로토콜 설정이나 IP, port 등 설정에 틀린게 있는지 봅니다.
 그 뒤에  FTP 계정 관리자를 엽니다.
사용자 삽입 이미지

4. 제대로 되면 아래와 같이 됩니다. 원하는 디렉토리, 파일을 클릭해서 파일을 원격으로 편집할수 있습니다.
사용자 삽입 이미지

처음 파일 만들때.. 전 그냥 SSH 창에서 vi main.c 엔터 -> :wq 해서 빈 파일을 만든뒤 편집했습니다 >_<;;

음.. 울트라 에딧을 쓰면서 putty의 vi 를 같이 하다 보면..
울트라 에딧에서 파일 다 코딩하면 습관적으로 :wq
vi 에선 습관적으로 ctrl+s 키를 누르더군요.. orz

+ Recent posts