Useful Solutions2012. 10. 26. 00:42

안녕하세요. Windows Azure MVP 남정현입니다.

오늘 소개해드리려고 하는 내용은 ClickOnce용 패키지를 만들었을 때 유용하게 활용하실 수 있는 팁입니다. 보통은 같이 만들어지는 setup.exe 프로그램을 통해서 ClickOnce 패키지가 시작되도록 배포하는 것이 일반적이겠지만, 이 setup.exe를 대신하여 여러분만의 고유한 Bootstrapper를 제작할 수 있는 방법이 있습니다. 바로 ClickOnce의 주요 핵심 DLL인 DFSHIM.DLL 파일의 API 2개를 활용하는 것인데요, 지금 소개하려는 API를 보통은 rundll32.exe 프로그램을 이용해서 호출하는 것으로만 구글의 검색 결과에 보통 열거됩니다. 그러나 이 기능을 rundll32.exe 프로그램에 의존하지 않고 직접 프로그래밍 코드에서 호출할 수 있는 방법은 없을까요?

rundll32.exe로 호출하는 API에 대한 특성 이해하기

rundll32.exe 프로그램은 약간의 트릭과 암묵적인 규칙을 기반으로 동작하는 시스템 유틸리티로 다소 게으른(?) 면이 있습니다. 특수한 경우를 제외하고 일반적으로 DLL 파일은 직접 실행할 수 없고 반드시 다른 EXE 파일에 동적이든 정적이든 링크되어 사용되야만 합니다. 프로그램 개발 공수 관점에서 보면 DLL에 중요 컨텐츠를 포함시켜놓았을 경우 번번히 이런 컨텐츠를 위해서 별 의미없는 EXE 파일을 빌드해야 하는 셈인데, 이러한 낭비적 요소를 제거하기 위해서 일반화된 DLL 호스트 및 실행 프로그램을 넣게 됩니다. 그러나 잘 아시겠지만, 사실 이는 잠재적으로 보안 위협이 되는 부분도 있습니다.

다행히도 rundll32.exe는 무분별, 무절제하게 아무렇게나 들어오는 입력을 모두 받아들이는 것이 아닙니다. 이에 대한 상세한 규칙은 Microsoft KB164787 문서 (http://support.microsoft.com/kb/164787) 에 상세하게 기록되어있으며 내용을 요약하면, RUNDLL32.EXE로 호출할 수 있는 함수 시그니처는 대강 아래와 같은 형태로 제약됩니다.

  • void __stdcall <Function>W(HWND hwnd, HINSTANCE hinst, LPCWSTR lpszCmdLine, int nCmdShow);
  • void __stdcall <Function>(HWND hwnd, HINSTANCE hinst, LPCSTR lpszCmdLine, int nCmdShow);
  • void __stdcall <Function>(void);

이 글을 작성하는 현 시점에서 16비트 운영 체제는 일상적으로 사용되지 않고, 32비트 및 호환 운영 체제 가운데에서도 NT 커널을 계승하는 운영 체제가 주로 사용됨을 감안하였을 때, 보통 위와 같이 시그니처들이 있다고 볼 수 있습니다. W라는 접미사가 붙는 것은 세 번째 매개 변수가 문자열 버퍼를 포함하고 있기 때문에 적용되는 Windows 프로그래밍 환경에서의 Convention입니다. 이와 같이 Wide String을 지원하는 함수가 있다면 가장 적극적으로 먼저 쓰이게 됩니다. 그리고 해당되는 함수가 없다면 Ansi String을 지원하는 두 번째 후보가 차선책으로 쓰이게 됩니다. 만약 별도의 파라미터가 없이 불린다면 세 번째 시그니처에 해당되는 함수가 채택됩니다.

DFSHIM.DLL의 문서화되지 않은 API 두 가지

DFSHIM.DLL은 .NET Framework 2.0과 함께 배포되는 ClickOnce의 핵심 기능을 포함하는데, 확장자가 .application인 파일을 실행해주거나 ClickOnce와 직접 확장자를 연결시킬 경우 연결 프로그램으로서 실행해주는 등의 기능, 그리고 ClickOnce 캐시 저장소 초기화 등의 기능을 담당합니다. 인터넷 자료를 검색해보면 대개는 COM 기반의 API나 제한된 몇 종류의 API만을 이야기하는 것으로 이야기가 잘 보입니다.

그러나 공식적으로 사용되면서도 정확하게 문서화되어있지 않은 API가 두 종류가 있으며 사실은 더 사용하기 쉬운 API가 두 종류가 있습니다. 바로 ShOpenVerbApplication(W), CleanOnlineAppCache에 관한 것인데, 양쪽 모두 rundll32.exe로 실행하는 방법은 아래와 같다고 나오지만 실제 프로그래밍 언어에서 다루는 방법에 대한 문서가 거의 없습니다.

  • %windir%\system32\rundll32.exe dfshim.dll,ShOpenVerbApplication <.application 파일의 경로나 URL>
  • %windir%\system32\rundll32.exe dfshim.dll,CleanOnlineAppCache

위와 같이 실행하는 방법 말고 더 간단한 방법은 없을까요? 앞에서 소개한 내용을 바탕으로 시그니처를 대입하면서 맞추어보니 아래와 같이 정의할 수 있었습니다.

  • typedef void (WINAPI *ShOpenVerbApplicationWProc)(IN HWND, IN HINSTANCE, IN LPCWSTR, IN int);
  • typedef void (WINAPI *ShOpenVerbApplicationAProc)(IN HWND, IN HINSTANCE, IN LPCSTR, IN int);
  • typedef void (WINAPI *CleanOnlineAppCacheProc)(VOID);

위의 함수 포인터에 대한 선언을 활용하여 _UNICODE 매크로 선언 여부에 따라 동적으로, 그리고 선택적으로 호출할 수 있도록 만들 수 있었습니다. (Visual C++ 컴파일러 기준)

// 함수 포인터 선언
typedef void (WINAPI *ShOpenVerbApplicationWProc)(IN HWND, IN HINSTANCE, IN LPCWSTR, IN int);
typedef void (WINAPI *ShOpenVerbApplicationAProc)(IN HWND, IN HINSTANCE, IN LPCSTR, IN int);
typedef void (WINAPI *CleanOnlineAppCacheProc)(VOID);
// 조건부 매크로 선언
#ifdef _UNICODE
 #define ShOpenVerbApplicationProc ShOpenVerbApplicationWProc
 #define ShOpenVerbApplicationName "ShOpenVerbApplicationW"
#else // _UNICODE
 #define ShOpenVerbApplicationProc ShOpenVerbApplicationAProc
 #define ShOpenVerbApplicationName "ShOpenVerbApplication"
#endif // _UNICODE
// 변수 선언
 HINSTANCE hLibrary;
 ShOpenVerbApplicationProc pProc;
 CleanOnlineAppCacheProc pClearProc;
 // DLL 로드 시도 및 함수 검색 (DLL 로드에 실패한 경우 .NET Framework 설치를 유도할 수 이
 BOOL LoadDFSHIM(void) {
  hLibrary = LoadLibrary(_T("DFSHIM.DLL"));

  if (hLibrary == NULL)
   return FALSE;

  pProc = (ShOpenVerbApplicationWProc)GetProcAddress(
   hLibrary,
   ShOpenVerbApplicationName);

  pClearProc = (CleanOnlineAppCacheProc)GetProcAddress(
   hLibrary,
   "CleanOnlineAppCache");

  if (pProc == NULL || pClearProc == NULL) {
   pProc = NULL;
   pClearProc = NULL;
   FreeLibrary(hLibrary);
   return FALSE;
  }

  return TRUE;
 }
 // 프로그램 종료 시 호출하여 자원 할당을 해제
 VOID UnloadDFSHIM(void) {
  if (pProc)
   pProc = NULL;

  if (pClearProc)
   pClearProc = NULL;

  if (hLibrary)
  {
   FreeLibrary(hLibrary);
   hLibrary = NULL;
  }
 }
// ClickOnce application 시작 시 호출
if (this->hLibrary != NULL && this->pProc != NULL)
{
  this->pProc(NULL, NULL, _T("ClickOnce .application 파일 경로 또는 URL"), SW_SHOW);
}
// 기존 Online 전용 App의 Cache를 삭제할 때 호출 (설치 시 문제가 있을 경우 활용 가능)
if (this->hLibrary != NULL && this->pClearProc != NULL)
{
  this->pClearProc();
}

위와 같이 C/C++ Application에서 간단하게 ClickOnce Online App 및 Offline App 설치를 호출할 수 있고, Online App Cache를 초기화할 수 있습니다.

결론

Windows Desktop App 가운데에서도 .NET으로 배포하는 App의 경우 설치 도입부부터 특별한 사용자 경험을 제공하기 위한 목적으로 위의 기능을 활용하면, setup.exe 파일 대신 여러분이 직접 디자인한 Setup Bootstrapper를 만들어 배포할 수 있고, 혹은 rundll32.exe 프로그램을 그대로 이용하여 바로가기 아이콘을 만드는데 활용할 수도 있습니다.

이 글에 대한 프리뷰 이미지 출처: http://hummingbird.tistory.com/3614

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Windows + .NET2012. 9. 15. 20:37

안녕하세요. Windows Azure MVP 남정현입니다. 오늘은 Visual Studio 2012 출시와 더불어서 Express Edition의 업그레이드에 대한 이야기를 전해드리려고 합니다.

개인적으로 매우 좋아하고 아끼는 Visual Studio 제품 라인 업 중에 Express Edition이 있습니다. 무료로 제공되는 개발 도구임에도 기능에서나 활용 면에서 부족함이 전혀 없고, 제 스스로에게 있어서 작업 시간을 줄여주고 시행 착오를 최소화하는데에 지대한 공헌을 하는 멋진 개발 툴입니다.

이번 2012 라인 업에서는 아래와 같이 구성이 변경되었습니다.

  • Visual Studio 2012 Express for Web: 기존의 Visual Web Developer 2010을 이어서 업그레이드된 버전으로 ASP.NET 4.5와 Windows Azure 최신 개발 툴킷, Silverlight 개발 환경등을 포함하고 있습니다.
  • Visual Studio 2012 Express for Desktop: 기존의 Visual C# Express 2010, Visual Basic .NET Express 2010, Visual C++ Express 2010을 통합하여 데스크탑 응용프로그램 개발에 최적화된 버전으로 업그레이드되었습니다.
  • Visual Studio 2012 Express for Windows 8: Windows 8에서 새로 추가된 Windows Store 앱을 만들기 위하여 필요한 개발 도구로 동시에 Expression Blend for Windows 8이 같이 설치됩니다.
  • Visual Studio Team Foundation Server 2012 Express: 고가의 상용 버전 제품으로만 알려져있었던 Team Foundation Server도 Express 버전을 새로 출시하게 되었습니다. 소규모 개발 팀을 운영 중인 경우 한 번즈음 고려해볼 수 있는 형상 관리, 작업 관리, 빌드 자동화를 제공합니다.

언어 별로 나누어져 있었기 때문에 장점이자 단점으로 동시에 작용하던 작고 가벼움은 아쉽게도 더 이상 존재하지는 않습니다. 그렇지만 Express Edition 특유의 한계를 극복하고 더 강력한 기능을 더하고 단순히 학습용이 아닌 소규모 개발 팀을 위한 배려를 모두 포함하고 있다는 것은 매우 기쁜 일입니다.

그리고 실제로 Visual Studio 2012 전체 버전을 구입하시기 전에 제품의 표면적인 기능만을 제한된 시간 내에 평가해야 하는 트라이얼 버전 대신, 실제 업무에도 자연스럽게 반영해볼 수 있는 Express Edition을 통해서 충분한 시간을 가지면서 활용하시면 좀 더 좋은 부분을 많이 보실 수 있을 것이라고 기대합니다.

Web과 Desktop 버전은 Windows 운영 체제 버전과 관계없이 사용이 가능하며, Windows 8 버전의 경우에는 실제로 Windows 8 운영 체제 위에서 실행되어야만 개발 환경 구축이 가능합니다. 그리고 이전과 마찬가지로, 무료로 사용이 가능하고 상용으로도 활용이 가능하지만 설치 후 기간 내에 Microsoft 등록 페이지에 가서 제품에 대한 25자리 등록 번호를 받아서 등록해야 하는 절차는 변함 없습니다.

2012 Express Edition과 2010 Express Edition을 다운로드하시려면 http://www.microsoft.com/visualstudio/kor/downloads 페이지로 가시면 됩니다. :-)

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

  1. 현재 네이버 메인에 나오고 있습니다.

    2013.01.28 15:38 신고 [ ADDR : EDIT/ DEL : REPLY ]

이벤트2010. 11. 19. 00:00

Visual Studio 2010 팀 블로그 운영진 분의 직강을 들으실 수 있는 특별한 세미나 세 편이 연속 기획되어있습니다. 이번 시리즈 세미나에서는 Visual Studio 2010을 통하여, 그 중에서도 특별히 Visual C++ 개발자들을 위한 세미나 두 편과 함께, Visual Studio 2010의 발전 가능성과 방향성을 진단해볼 수 있는 세미나로 구성되어있습니다.

그 중에서도 이번 12월 2일 세미나에서는 Visual C++ MVP이신 최흥배 MVP님의 강연이 있을 예정이며, Visual C++ 개발자 여러분들의 많은 관심과 참여를 부탁드립니다. :-)

개발자 여러분 안녕하세요.
Visual Studio 2010 이 여러분들의 개발자로서의 삶에 어떤 혁신적인 변화를 가져다 드릴 수 있는지 알려드리는
Visual Studio 2010 세미나 시리즈가 개최됩니다.
총 3회로 이루어진 본 Visual Studio 2010 세미나 시리즈는 개발 퍼포먼스 향상과 고품질 애플리케이션 개발을
꿈꾸시는C++ 개발자 여러분들을 위한 첫 번째, 두 번째 세미나, 그리고 완벽 팀웍을 바탕으로 소프트웨어 가시화 및
테스트 자동화를 통해 무결점 소프트웨어 개발을 꿈꾸시는 개발자 여러분들을 위한 세 번째 세미나로 구성되어
있습니다.

그 동안 경험해 보시지 못했던 편안하고 파워풀한 개발자로서의 삶을 만들어 드릴 Visual Studio 2010.
이번 겨울에는 이 세 번의 Visual Studio 2010 세미나 시리즈를 통해 여러분들의 개발자로서 가지고 계신 상상력과
잠재력을 실제 애플리케이션으로 보다 빠르고 파워풀하게 만들어 내실 수 있는 Skill-Up 의 기회로 삼으셨으면 합니다.
본 세미나는 여러분들의 보다 많은 참여를 위해 저녁시간에 진행되오니 저희와 함께 추운 겨울 밤을 뜨거운 학구열로
함께 보내주시면 감사하겠습니다.

Visual Studio 2010 세미나 시리즈에서 여러분들을 만나 뵙기를 바라겠습니다.
감사합니다.
세미나 일시 : 2010.12.02(목) 18:30~21:00 세미나 참석 대상 : C++ 개발자 여러분들
최흥배 선임연구원
- (현)마이에트 엔터테인먼트에서 Gunz2 서버 개발
- 2009, 2010 Microsoft Visual C++ MVP
- KGC 2008, 2009 강연
18:30 ~ 19:00 등록
19:00 ~ 19:50 Session 1 : Visual Studio 2010이 제공하는 새로운 가치
Visual Studio 2010에서 새롭게 선보이는 개발자 생산성 향상을 위해 보강된 사용 편의성 기능부터 고품질의 소프트웨어 개발에
필요한 품질관리 강화 기능에 이르는 다양한 기능들에 대해 안내해 드립니다.
19:50 ~ 20:00 휴식시간
20:00 ~ 20:50 Session 2 : 개발자, 개발팀의 미래를 위한 개발환경 업그레이드 방안
다양한 Visual Studio 사용자분들이 고민하시는 “왜 업그레이드를 해야지?”, “업그레이드를 어떻게 하지?”와 같은 주요
두가지 질문에 대한 명쾌한 해답을 드리는 세션으로, 업그레이드에 대한 공감대를 뿐만 아니라 업그레이드시 고려 및
유의해야 할 실무적인 Tip을 안내해 드립니다.
20:50 ~ 21:00 맺음말 경품 추첨
 
• 세미나 일시 : 2010.12.16(목) 18:30~21:00
• 세미나 참석 대상 : C++ 개발자 여러분들
• 세미나 강사 : 최흥배 선임연구원 (마이에트 엔터테인먼트)
• 세미나 일시 : 2011.01.13(목) 18:30~21:00
• 세미나 참석 대상 : 혁신을 꿈꾸는 모든 개발자 여러분들
• 세미나 강사 : 강성재 차장(한국마이크로소프트)
• 본 교육은 좌석이 한정되어 있으며 선착순으로 마감됩니다.
• 교육 후 추첨을 통하여 푸짐한 경품을 드립니다.
• 본 교육에서는 저녁식사를 제공해 드립니다.
• 주차권은 제공되지 않습니다.
행사 등록사무국 02) 598-9898 rgst@neodigm.com

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

PaaS2010. 11. 2. 23:45

Windows Azure 코드 샘플을 한 곳에 모아서 찾아보기 쉽게 만든 블로그 아티클이 있어서 올려봅니다. Windows Azure 실전 예제에 관심있으신 분들께 도움이 되셨으면 합니다. :-)

예제 응용프로그램

아키텍처 및 디자인 예제

  • 코드 갤러리
    • 동적 스케일링 샘플 - 처리량에 대응하여 동적으로 인스턴스의 수가 늘어나고 줄어드는 것을 보여주는 다중 역할 샘플입니다: http://code.msdn.microsoft.com/azurescale
  • 본사 DPE 부서에서 작성한 예제
    • Project Riviera - 동적 스케일링 샘플에서 더 확장된 예제로, 윈도 애저 스토리지, Windows Workflow, 액티브 디렉터리 페더레이션 서비스, Patterns & Practices Enterprise Library 캐싱 및 로깅 응용프로그램 블럭, 윈도 라이브 ID 인증 등 엔터프라이즈 및 아키텍처에서 등장하는 기술들이 골고루 사용된 고급 샘플입니다: http://code.msdn.microsoft.com/riviera
  • Patterns & Practice - Windows Azure Platform을 위한 아티클이 새로 업데이트되고 있는 중입니다.

클레임 / 아이덴티티 예제

환경 설정

데이터 액세스 및 스토리지 예제

응용프로그램 배포

일반적인 내용들

로깅 및 운영 전략

기존 응용프로그램을 클라우드로 마이그레이션
서비스 버스 (AppFabric)
서비스 관리 API
SQL 애저
WCF (Windows Communication Foundation)
윈도 애저 스토리지
Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

이벤트2010. 10. 31. 15:56

이번 세미나는 C++을 사용하시는 전문 개발자 여러분과 게임 개발자 여러분들을 위한 세미나로, DirectX 11, Intel Parallel Studio, 병렬 프로그래밍 컨셉, PBB 기반 고수준 병렬 프로그래밍 4개 주제를 테마로 하는 기술 세미나입니다. 특히, 평소에 저희 Visual Studio 2010 한국 공식 팀 블로그 (http://www.vsts2010.net) 를 통하여 DirectX 11과 Visual C++ 관련 아티클을 자주 찾아주셨던 분들께 특별히 권해드리는 세미나입니다. :-)

장소: 양재동 엘타워 (ELTOWER) 그레이스 홀 (6F) / 일정: 2010년 11월 6일 수요일 (정정합니다. 2010년 11월 9일 화요일) 오후 1시 30분부터 / 참가 보증금: 2,000원

참가 신청 바로가기: http://www.microsoft.com/visualstudio/ko-kr/strategy-seminar.html

참가 신청 바로가기: http://www.microsoft.com/visualstudio/ko-kr/strategy-seminar.html

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

이벤트2010. 9. 13. 15:10

이른 아침이고, 월요일임에도 불구하고 열린 세션임에도 불구하고 강의장을 가득 채워주신 청중 여러분들께 진심으로 감사의 말씀을 올리며, 최종 수정 버전의 강의 자료를 올립니다. 이 강의 자료에 있는 샘플들에 대한 원본 링크는 아래에 같이 적어두었으니 관심있으신 분들께서는 참조하여 주십시오.

아울러서, 15일에 오디토리움 101에서 저녁 5시부터 6시까지 진행되는 VSTS 2010 팀의 최흥배 MVP님의 세션도 많은 참석 부탁드립니다. 이 세션에서는 Visual C++ 10.0 (마케팅 버전 2010)에서의 주요 변경 사항과 향상된 디버깅 기법에 대한 내용이 소개될 예정입니다. 실무에서 C++ 기반의 프로그래밍을 활용하시는 분들의 경우, Visual C++ 2010의 향상된 언어 기술과 더불어서 64비트 컴파일 기술, 그리고 오늘 세션에서 소개해드렸던 것과 같이 클라우드 위에 입주시킬 수 있는 Native Application Server를 제작하신다면 훌륭한 성능의 소프트웨어 서비스를 구현하실 수 있을 것입니다.

   

감사합니다. :-)

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Exploring2010. 9. 9. 13:19

Windows Phone 7에 대한 관심이 뜨거운 요즈음, Windows Embedded 역시 새 버전에 대한 CTP가 공개되었습니다. Windows 7 운영 체제를 실행하는 컴퓨터와 가장 연동이 잘 된다는 사실에 많은 부분을 강조하고 있으며, Windows Phone 7으로 전환되는 동안 한 동안 많은 오해가 있었던 부분인 Native Development Feature (C/C++ based)에 대한 부분도 오해가 풀린듯 합니다. ㅎㅎ

Windows Embedded Compact 7 CTP 개발 도구 및 관련 최신 정보의 구독을 위해서는 Windows Live ID (http://www.live.com)이 필요하며, https://connect.microsoft.com/directory/non-feedback 에서 체험판 프로그램 신청이 가능합니다. 이곳을 통하여 신청을 완료한 후 최신 버전의 SDK를 다운로드받아 테스트 가능합니다. 응용프로그램 디자인을 위해서는 Expression Blend 3를 사용해야 하며, 없을 경우 Trial 버전을 http://www.microsoft.com/downloads/details.aspx?FamilyID=e82db5e2-7106-419e-80b0-65cce89f06bb&displaylang=en 에서 다운로드받아 이용하실 수 있습니다. 자세한 정보는 http://www.microsoft.com/windowsembedded/en-us/products/windowsce/compact7.mspx 에서 확인 가능합니다.

Connected Experience

멀티미디어에 대한 연결과 사용

* 미디어 라이브러리를 기반으로 하는 단순화된 미디어 관리
* MPEG-4 및 HD 지원 및 향상된 미디어 스트리밍
* 써드파티 컨텐츠를 위한 유연한 플러그 인 아키텍처

Microsoft Windows 7과의 긴밀한 연동
* Windows Device Stage 지원
* MTP 기반의 데이터 및 미디어 동기화

Office 문서 및 개인 정보 연동
* 새 버전의 Office 문서 뷰어 지원 (OOXML 기반 문서 지원)
* AirSync 및 Microsoft Exchange 동기화 지원

Rich User Experiences

확장 가능한 사용자 인터페이스 프레임워크
* Windows Embedded용 Silverlight (http://www.microsoft.com/windowsembedded/en-us/products/windowsce/silverlightforwe.mspx) 기반의 새로운 사용자 인터페이스 디자인
* Microsoft Expression Blend 기반의 디자이너 경험 제공
* XAML 코드 생성 도구에 의한 빠르고 확장 가능한 장치 사용자 인터페이스 제공

향상된 데스크톱 브라우징
* 최신 표준 기술을 준수하는 Internet Explorer 브라우징 엔진 탑재
* Tabs, Panning, Zoom 동작 지원
* Adobe Flash 10.1 기반의 멀티미디어 컨텐츠 지원

자연스러운 터치 입력
* 고감도의 터치 입력을 기반으로 하는 사용자 인터페이스 설계 가능
* 다중 터치 입력 지원
* 제스처 인식 기능 지원

Highly Reliable Platform

Visual Studio 연동
* Visual Studio 및 Expression Blend를 통한 개발 지원
* Visual Studio의 경우, C/C++ 기반 개발 환경 지원
* Windows Embedded Developer Update (http://www.microsoft.com/windowsembedded/en-us/news/pressreleases/esc-west1.mspx)를 통한 기능 업데이트의 제공을 단순화
* 최소한의 사용자 입력을 기반으로 하는 새로운 설치 경험

최신 하드웨어의 이점을 활용
* ARM v7 프로세서 지원
* Open GL ES 2.0 기반의 향상된 그래픽 성능
* 멀티코어 아키텍처 기반의 고성능 및 SMP 지원

개선된 신뢰성 및 뛰어난 성능
* Windows 7 기반의 네트워크 기술을 기반으로 하는 향상된 네트워킹
* 안정성있는 무선 연결 및 WiFi 지원
* Bluetooth 2.1 지원 / 최신 하드웨어와의 연결

2010.09.20 Update: 아크몬드님의 네이버 오픈 캐스트에 글이 같이 소개되었습니다.



Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

  1. 멋집니다!!

    2010.09.09 19:58 신고 [ ADDR : EDIT/ DEL : REPLY ]
  2. 비밀댓글입니다

    2010.09.20 12:10 [ ADDR : EDIT/ DEL : REPLY ]

이벤트2010. 7. 28. 21:42

한국 Visual Studio 공식 팀에서 2010년 8월 28일 토요일 오후 1시 30분부터 5시까지 선릉역 부근 웹타임 교육센터에서 Visual Studio Camp #1을 엽니다. Native Developer Track에는 최성기님, 임준환님, 조진현님께서, .NET Developer Track에는 강보람 Visual C# MVP님, 박세식님, 오태겸님께서, Enterprise Developer Track에서는 김병진 Team System MVP님, 엄준일 Team System MVP님, 정홍주 SQL Server MVP님께서 알찬 내용으로 세미나를 꽉 채워주실 것입니다. Visual Studio 2010에 대한 새로운 기능뿐만 아니라, DirectX 11, WCF, C# 4.0, ASP.NET MVC 2에 대한 심도있는 주제들을 다루는 의미있는 시간이 될 것입니다. 세미나에 많은 관심과 참여를 부탁드리며, 참가 신청은 http://onoffmix.com/event/1676 에서 가능합니다. :-)

 


 

저희 "한국 Visual Studio 공식 " 에서 세미나를 주최합니다.

 

저희 "한국 Visual Studio 공식 " 온라인 블로그(http://vsts2010.net) 통해 다양한 분야의 전문가들이 활동하고 있습니다. 그리고 동안 저희 팀원들은 다양한 세미나 경험을 바탕으로 많은 강사진을 구축하였습니다. 경험을 바탕으로 저희 팀에서 주최하는 세미나를 진행하게 되었습니다.

 

다가오는 2010/08/28일에 Visual Studio Camp #1 진행하오니 많은 성원 부탁 드립니다.

 

세미나 등록은 아래의 링크를 통해 신청할 있습니다.

http://onoffmix.com/event/1676

 


Visual Studio Camp #1


- 주최 : 한국 Visual Studio 공식 팀
- 일시 : 2010년 8 28 토요일 오후 1:30~5
- 장소 : 타임 교육 센터
- 참가비 : 무료



세미나 아젠다

 

Native 트랙

.NET 트랙

Enterprise 트랙

14:00 ~ 14:50

Visual Studio 2010 : C++0x와 Windows 7

 

 

 

최성기

그것이 알고싶다 - C# 4.0의 변화, 그 진실은 무엇인가. 희망인가? 또 다른 혼란인가?

 

강보람 C# MVP

VS Team Foundation Server 2010 의 새로운 변화

 

 

김병진 Team System MVP

15:00 ~ 15:50

비주얼 스튜디오 2010 의 Concurrency Runtime 을 이용한 멀티 코어 제대로 활용하기

 

임준환

좋은 프레임워크 있으면 소개시켜줘 - ASP.NET MVC

 

 

 

박세식

소프트웨어 품질 향상을 위한 다양한 테스트 기법

 

 

 

엄준일 Team System MVP

16:00 ~ 16:50

DirectX11 을 기다리며...

 

 

조진현

Beginnig WCF

 

 

오태겸

SharePoint 2010 Enterprise 솔루션 개발

 

정홍주 SQL Server MVP

 




발표 내용 소개
Native 트랙 Visual Studio 2010 : C++0x와 Windows 7
동안 .NET 영역으로 적잖이 편중되었던 Visual Studio의 버전업에 비해 이번 2010 버전에서는 Native Code 개발환경에서도 많은 변화가 찾아왔다. C++0x 표준 반영에 의한 문법의 변화, 새로운 라이브러리 제공(Concurrency Runtime Library), Windows 7의 최신 기능들을 제어하기 위한 SDK의 업데이트 등이 그것이다. 본 세션을 통해 C++의 문법적인 변화와 Windows 7 기능 구현을 위한 SDK의 업데이트 사항들을 정리해본다.

비주얼 스튜디오 2010 의 Concurrency Runtime 을 이용한 멀티 코어 제대로 활용하기
요즘 가정의 PC 에 멀티 코어 프로세서가 많이 보급되어 있습니다. 하지만 실제로 PC 에 설치된 코어들을 모두 사용하는 애플리케이션들은 많지 않습니다. 이렇게 낭비되는 자원을 C++ 개발자가 쉽게 사용할 수 있도록 도와주는 Concurrency Runtime 을 비주얼 스튜디오 2010에서 제공합니다. 이 Concurrency Runtime 을 어떻게 시작해야 할지 알아보겠습니다.

DirectX11 을 기다리며...
조금씩 정보가 공개되면서 많은 변화를 예고하고 있는 DirectX11 에 대해서 살펴 볼 것입니다. 특히나 Tessellation, DirectCompute, Multi-threading 을 위한 기본 개념과 작업들에 대해서 체크해 볼 것입니다.
.NET 트랙 그것이 알고싶다 - C# 4.0의 변화, 그 진실은 무엇인가. 희망인가? 또 다른 혼란인가?
PDC 2008에 울려 퍼진 C# 4.0의 소식. 그 소식을 듣고 많은 사람들은 기대와 혼란을 가지게 되었다. C#은 분명히 정적 언어인데, 동적 언어에나 있을 법한 기능을 추가한다니? 이제 와서 뒷북일 수도 있는 C# 4.0의 변화에 대한 진실, 그 마지막 시리즈가 이제 시작된다. :)

좋은 프레임워크 있으면 소개시켜줘 - ASP.NET MVC
동안 아주 미묘하게 아쉬웠던 ASP.NET. 가려운 곳을 긁어줄 대안의 프레임워크가 나타났다. 웹 개발자들 한테 참~ 좋은데, 웹 개발자들 한테 정말 좋은데, 이걸 말로 그냥 할 수 없어서, 이번 기회에 소개한다.

Beginnig WCF
WCF는 서비스 지향 프로그래밍을 위해 마이크로소프트에서 개발 및 지원하는 기반 기술이며, 기존의 .NET 웹 서비스에 비해 유연성과 확장성이 뛰어나 최근 많은 관심을 받고 있습니다. 본 세션에서는 WCF가 무엇인지? 어떤 장점이 있는지? 그리고, WCF 를 이용하기 위해선 무엇이 필요한지? 에 대해 함께 알아보고, 마지막으로, WCF의 활용 예를 알아보도록 하겠습니다.
Enterprise 트랙 VS Team Foundation Server 2010 의 새로운 변화
Visual Studio Team Foundation Server 2010의 혁신적인 변화와 개선 부분, 프로젝트 및 형상관리와 Agile의 Scrum 을 이용한 방법론을 알아보고, 단지 소스 체크인/아웃만 하는 Visual Source Safe에서 업그레이드 하는 방법에 대하여 알아봅니다.

소프트웨어 품질 향상을 위한 다양한 테스트 기법
소프트웨어는 개발 및 릴리즈 과정까지 수 많은 과정을 겪는데, 소프트웨어가 점진적으로 진화함에 따라 결함의 발생률이 증가합니다. 이를 개선하기 위한 테스트 기법 단위 테스트, WhiteBox 테스트, 화면 테스트, 성능 테스트, 부하 테스트 다양한 테스트 기법을 알아봅니다.

SharePoint 2010 Enterprise 솔루션 개발
SharePoint 2010은 기업 협업 플랫폼으로 개발자들은 VS 2010을 이용하여 더 생산성 있고 효과적인 SharePoint 2010 개발을 진행할 수 있습니다. 본 세션에서는 SharePoint 2010 개발에 대한 가장 필요한 내용을 구체적으로 알아보며 이를 통해 가장 많은 요구사항에 대한 실무 솔루션을 구성하는 방법에 대한 내용을 알아보겠습니다.



발표자 소개
Native 트랙 최성기 / Visual Studio 공식 팀
엔씨소프트에서 온라인 게임 서버를 개발하고 있으며, 비주얼 스튜디오 2010 공식 팀 블로그 (http://vsts2010.net) 에서 MFC와 윈도우7 카테고리를 맡아 스터디를 하고 있다. 최근 UX 시장의 핫이슈인 ‘멀티터치’에 대해 많은 관심을 갖고 있다.
임준환 / Visual Studio 공식 팀
Visual Studio 2010 공식 팀 블로그( http://vsts2010.net ) 에서 C++, 게임 관련 필자로 활동하고 있다.
조진현 / Visual Studio 공식 팀
현재
 클라이언트 게임 프로그래머로써 재직 중입니다. Visual Studio 2010 공식 블로그(http://vsts2010.net에서 DirectX11 부분에서 활동 중입니다.
.NET 트랙 보람 / Visual Studio 공식 팀 시삽 / Microsoft C# MVP
Visaul Studio 공식
팀의 닷넷 파트 시삽을 맡고 있으며, Visual C# MVP이다. MSDN 주간 세미나, Techdays 2009, 2010 Spring, REMIX 10에 참여했으며, '그것이 알고싶다'를 2004년 부터 거의 빼놓지 않고 다 본 경력의 소유자이다. 개인 블로그 '워너비의 소프트웨어 팩토리'(http://blog.naver.com/netscout82)를 운영 중이며, 프로그래밍과 전혀 상관없는 이야기를 쓰고 있다.
박세식 / Visual Studio 공식 팀
아직까지는 꿈
많은 유부남 청년이다. 아이가 생기면 시간이 없다는 말에 몸서리 치면서 노력 중이다. Visual Studio 공식 팀 블로그에서 ASP.NET MVC 관련 포스팅을 하고 있고, 개인 블로그 sses's blog(http://sses.tistory.com)를 운영 중이다.
오태겸 / Visual Studio 공식 팀
오태겸, 현재 Hostway 에서 근무하고 있으며, 개인 블로그(
http://ruaa.tistory.com)와 Visual Studio 2010 공식 팀 블로그(http://vsts2010.net)에서 WCF 카테고리를 통해 있는 지식, 없는 지식 총 동원해가며, WCF에 관한 포스팅을 하고 있다.
Enterprise 트랙 김병진 / Visual Studio 공식 팀 시삽 / Microsoft Team System MVP / MCT
김병진 MCT/Microsoft MVP로 Visual Studio 2010 팀 블로그(
http://vsts2010.net)에서 활동하고 있으며, ALM 교육과 컨설팅을 통해 Microsoft 의 기술과 플랫폼기반의 개발과 설계 관련하여 강의과 컨설팅을 하고 있으며, 우리나라 소프트웨어 공학의 발전을 위해 열심히 노력하고 있습니다.
엄준일 / Visual Studio 공식 팀 대표 시삽 / Microsoft Team System MVP
엄준일 Microsoft Team System MVP 로 활동 하고 있으며, 개인 블로그(http://blog.powerumc.kr) 와 트위터(@powerumc) 를 통해 .NET 기술을 전파하고 있다. 그리고 Visual Studio 2010 공식 팀 블로그(http://vsts2010.net) 의 대표 시삽으로 팀 블로그와 트위터(@vsts2010) 를 운영하고 있다.
정홍주 / Visual Studio 공식 팀 / Microsoft SQL Server MVP
웹타임 교육센터에서 SQL, .NET 강의와 .NET, SharePoint 컨설팅을 하고 있다.
Microsoft SQL Server MVP 로 활동 하고 있으며 데브피아의 SQL Server 2005 시샵이다. SharePoint 2010 책을 집필하고 SharePoint 2010 관련 동영상과 미니클립을 서비스하고 있으며 현재 Visual Studio 2010 공식 팀 블로그(http://vsts2010.net) 에서 SharePoint 2010 관련 블로깅을 하고 있다. 향후 SharePoint 2010 개발 관련 여러 내용을 Open Source 할 예정이다.


오시는 길



경품 안내
Microsoft USB 키보드 3
Microsoft 무선 마우스 3
MSDN 1년 구독권 2개


후원
웹 타임 교육 센터
 

참가 신청 바로가기: http://onoffmix.com/event/1676

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Exploring2010. 6. 10. 14:59

2005년 이후로 줄곧 Microsoft를 깊이있게 심층취재하는 기자들 사이에서 Microsoft의 차세대 운영 체제에 대한 이야기가 자주 회자되고 있습니다. 그 중 가장 많은 화제거리를 제공하는 소재는 단연 MIDORI 였습니다. 클라우드 컴퓨팅 기술과도 엮이면서 한층 더 궁금증을 증폭시키기도 했었지요. 그러나, 오늘 글에서는 MIDORI에 대한 이야기는 잠시 뒤로 미루고, 지금 볼 수 있는, 한창 개발 중인 운영 체제 두 종류를 대신 이야기해보기로 하겠습니다. Singularity는 현재 Codeplex에 게시되어있는 RDK를 실행하고 분석해본 후 제 나름대로 경험해본 특이한 사항들을 요약해서 적어놓은 것입니다.

Singularity는 2008년경에 Microsoft Research (이하 MSR)에서 Research Development Kit (이하 RDK)의 형태로 Codeplex 홈페이지에 올렸습니다. Singularity는 하드 디스크의 MBR 영역에 설치되는 작은 크기의 부트 로더 프로그램을 제외하고 모든 것이 관리 영역 안에 속하는 독특한 운영 체제입니다. 컴퓨터 과학에서 표현하는 3단계 Ring Protection Layer로 말할 것 같으면, 가장 핵심 부분인 Ring 0부터 가장 외부적인 부분인 Ring 3까지 전부 가비지 컬렉터와 관리되는 런타임 아래에서 관리되는 셈입니다.

Singularity RDK에는 OS의 소스 코드 외에도, Singularity에서 사용할 수 있는 응용프로그램을 제작할 수 있는 Bartok 컴파일러와 Singularity OS에 최적화된 CLR/CLI 라이브러리가 포함되어있습니다. Singularity 기반으로 실행되는 응용프로그램을 만들기 원한다면, C# 1.0의 문법을 기초로 하는 Spec#을 확장한 Singularity의 시스템 프로그래밍 언어인 Sing#을 사용할 수 있으며, Sing#으로 작성된 소스 코드를 Bartok 컴파일러로 컴파일하면 해당 프로세서 아키텍처에 맞는 직접적인 응용프로그램 코드가 생성되는 형태입니다. C/C++ 컴파일러와 다른점이 있다면, Bartok 컴파일러가 생성하는 코드에는 D 언어와 마찬가지로, 그러나 Java나 우리가 기존에 알고 있던 .NET Framework와는 달리, 자체적인 가비지 컬렉터를 내장하고 있다는 점입니다.

Sing# 언어의 경우는, 모든 경우를 다 살펴볼 수 없지만, Rotor Framework를 통해서 실체가 밝혀진 C#의 hidden keyword 중 하나인 __arglist와 같이 ECMA 규격 상에 포함되지 않은 특수 키워드들이 다수 포함되어있습니다. __arglist는 C/C++의 varargs와 대응되는 의미로 사용되었지만, Singularity 환경 아래에서는 관리 형식의 배열보다 좀 더 최적화된 (어떤 의미에서는 불안정한) 배열 타입을 제공하기 위한 것으로 보입니다.

Singularity는 연구 목적으로 활용되는 것 이상으로는 이용할 수 없는 라이선스 제약이 있습니다. 상용으로 채택할 경우 라이선스 위반이 됨을 유의해야 합니다. 이러한 제약 사항 아래에서, 자유롭게 소스 코드를 살펴보고, ISO 이미지를 다운로드받아서 VMware나 Windows Virtual PC에서 부팅시켜보시려면, http://singularity.codeplex.com/ 페이지에 제공된 소스 코드나 ISO 이미지를 다운로드받으시면 되겠습니다. :-)

그리고 오늘 아티클에서는 Singularity 외에 MSR과 관련되어있는 또 다른 연구형 운영 체제 한 종류를 더 짚어보기로 하겠습니다. 바로 Barrelfish입니다. Barrelfish는 캠브릿지 MSR과 스위스 취리히의 취리히 연방 공과대학교 산하 Systems가 공동으로 2007년 10월부터 진행 중인 오픈 소스 프로젝트이며, 변형된 BSD 라이선스인 3-clause-BSD 라이선스를 제시합니다. 기본 BSD 라이선스와는 달리, 소스 코드 / 바이너리와 관계없이 원저자의 이름을 명시해야 하고, 원저자의 이름을 Barrelfish 기반의 소프트웨어에 관하여 사용할 수 없다는 제약이 붙습니다.

Barrelfish OS는 C 언어와 어셈블리를 주로 사용하며, 현재 스냅샷 기준으로 x64 (AMD64) 모드를 대상으로 하며, 멀티 코어 프로세서에 최적화된 OS를 만드는 것에 관한 다양한 기술적 이론이 집약된 고성능 운영체제이지만, 리눅스나 윈도우와는 전혀 별개의 브랜치를 가집니다. 어떤 형태로 발전하게 될지는 알 수 없지만, 향후 출시될 Windows Server Family에도 영향을 줄 수 있는 부분처럼 보입니다. 그리고 Barrelfish 자체로도 연구 목적에 맞는 고성능 서버OS로 업그레이드할 계획이 있다는 것이 프로젝트 설명 페이지에 제시된 내용입니다.

Barrelfish의 홈페이지 (http://www.barrelfish.org)는 Barrelfish OS를 기반으로 운영되는 웹 서버에서 서비스 중이라는 특징적인 문구가 홈페이지 하단의 footer에 붙어있습니다. Public Domain에서 서비스할 수 있을만큼 OS가 고성능이고 안정적이라는 뜻으로 받아들여도 될 것입니다.

Barrelfish의 소스 코드를 구경하고 싶으시다면, http://www.barrelfish.org/barrelfish-20091219.tar.bz2 에서 다운로드하실 수도 있습니다.

앞으로 어떤 형태로 새로운 운영 체제들이 나타날지 아직은 아무도 알 수 없습니다만, 미래를 조심스럽게 예측해 보는 것은 참 의미있는 일이라고 생각합니다. 짧은 글이었지만, 클라우드 컴퓨팅, 그리드 컴퓨팅, 멀티코어 컴퓨팅 등 새로운 컴퓨팅 패러다임에 걸맞는 새 시대의 운영 체제를 미리 탐험해 보았습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Exploring2010. 2. 26. 10:53

Stackoverflow.com
Stackoverflow.com은 우리에게 "조엘 온 소프트웨어"로 잘 알려져있는 "조엘 스폴스키"와 "코딩 호러"로 잘 알려져있는 "제프 앳우드"가 함께 만든 웹 사이트로, Experts-Exchange 웹 사이트에 대한 Alternative Website로 많은 인기를 얻고 있습니다. 구글 검색 결과를 자주 접하시는 분들은 모두 동감하시겠지만, Experts-Exchange 웹 사이트의 검색 결과는 항상 "비용 지불"을 요구합니다.

 

Stackoverflow.com에는 실로 유용한 질문과 답변들이 가득한데, 정말 어려운 문제에 봉착했을 때 시원한 답변을 얻을 수 있는 경우가 많습니다. 이번에 제가 맡았던 씨티은행 외국환업무시스템의 닷넷 기반 프로젝트에서도 많은 도움을 얻을 수 있었습니다.

 

Stackoverflow.com은 2010년 2월 현재 약 13만 5천여명의 회원과 함께 약 51만 5천개의 Q&A 목록을 보유하고 있으며, C#, 자바, 닷넷, ASP.NET, PHP, 자바스크립트, C++, jQuery, 파이썬 및 아이폰에 대한 내용을 토론하는 스레드들로 채워져있으며 지금 이 시간에도 다양한 질문과 답변이 오고 가고 있습니다. Windows Azure에 대한 내용도 자주 회자되곤 합니다. (위키피디아 설명 인용 - http://en.wikipedia.com/wiki/Stackoverflow)

 

구글 검색 결과를 살펴보실 때, 사이트 주소에 Stackoverflow.com에서 검색한 결과가 있다면 놓치지 말고 꼭 살펴보시기를 권합니다. :-)

 

http://www.stackoverflow.com/

 

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2010. 1. 25. 16:03

MSIL 연산 지시어 중 하나인 modopt에 관한 정보를 구글을 통하여 검색해보다가, 눈에 띄는 자료 하나를 찾게 되어 블로그에 글을 올려봅니다. C++/CLI의 역사적인 배경을 설명하고, C++/CLI와 같이 레거시 언어에서 확장된 형태의 프로그래밍 언어를 바라보는 관점을 소개하고 있어 매우 유익하다고 생각합니다.

 

출처: http://msdn.microsoft.com/ko-kr/magazine/cc163484.aspx (MSDN Magazine)

 

목차

  • 설계 원리
  • Managed Extensions의 쇠퇴
  • 미래에 대한 기대
  • 프로그래밍의 진화
  • 최종 목표
  • 작별 인사

 

이번 달에는 그 동안 즐겨 사용해 온 질문과 대답 형식에서 벗어나 필자가 온라인에서 찾아낸 훌륭한 문서에 대해 소개하려 합니다. 몇 주 전에 필자는 C++/CLI에서 다음과 같이 const 함수를 선언할 수 없는 이유를 묻는 질문을 받았습니다.

 

// reference class
ref class A {
   void f() const; // NOT!
};

 

대답은 간단합니다. 규칙이기 때문에 어쩔 수 없다는 것입니다. CLI(Common Language Infrastructure)는 const가 무슨 의미인지도 모르는 Visual Basic®, Java, 심지어는 COBOL과 같은 다양한 언어를 지원하기 위해 설계되었습니다. 즉 CLI는 const 멤버 함수가 무엇인지 모르므로, CLI에서 이 함수를 사용할 수 없습니다.


대답을 보내고 나서 문득 기억 한구석에 있던 const와 관련하여 언어에 관계없이 컴파일러 힌트로 무언가 할 수 있었다는 내용이 떠올랐습니다. 곧바로 예전 칼럼을 찾아보니 2004년 7월에 const에 대한 질문에 대답한 적이 있었습니다. 사실 C++/CLI에서 const 멤버 함수는 선언할 수 없지만 const 데이터 멤버와 매개 변수는 가능합니다. 그림 1은 const 정적 데이터 멤버를 가진 참조 클래스를 사용하는 작은 프로그램의 예입니다. 이 프로그램을 컴파일한 다음 ILDASM을 사용하여 디스어셈블하면 다음과 같은 코드를 볼 수 있습니다.

 

field public static int32 
    modopt([mscorlib]System.Runtime.CompilerServices.IsConst)
        g_private = int32(0x00000001)

 

////////////////////////////////////////////////////////////////
// To compile type:
//    cl /clr const.cpp
//
#include 

ref class A {
   int m_val;
   // const data member allowed, will generate modopt
   static const int g_private = 1;
public:
   // public const member could be modified by Visual Basic or other
   // programs that don't know const -- so use literal instead.
   literal int g_public = 1;
   A(int i) { m_val = i; }
   void print();  // const;             // NO!--const fn not allowed
};

void A::print()
{
   printf("Val is %d\n",m_val);
}

int main()
{
   A a(17);
   a.print();
}

그림 1: const.cpp

 

MSIL 선언자인 Modopt는 선택적인 한정자이므로 CLI 사용자는 이 내용을 이해할 수 있다면 좋고, 그렇지 않다면 그냥 무시해 버리면 됩니다. 그러나 modreq 함수는 필수 한정자이므로 반드시 이해해야 합니다.

 

modreq의 예로는 Volatile이 있는데, volatile 참조는 운영 체제나 하드웨어, 심지어는 다른 스레드에 의해서도 언제든 변경될 수 있으므로 CLI 사용자가 Volatile을 사용하려면 Volatile이 무엇인지 알아야 합니다. 하지만 const는 선택적인 한정자입니다. 그러나 Managed Extensions는 C++ const 개체를 CLI 리터럴로 변환하는 반면, C++/CLI는 이런 작업을 하지 않기 때문에 주의해야 합니다. 공용 const 데이터 멤버를 선언한 경우 Visual Basic과 같은 언어로 작성된 클라이언트가 그 값을 바꿀 수도 있습니다. CLI 클라이언트에서 값을 바꿀 수 없도록 하려면 그림 1과 같이 개체 리터럴을 선언해야 합니다. 그렇다면 멤버 함수는 어떨까요? const 멤버 함수는 왜 지원되지 않는 것일까요?

 

설계 원리


필자의 대답에 대해 연구하던 중 Microsoft의 Herb Sutter가 작성한 "A Design Rationale for C++/CLI"라는 훌륭한 기사를 찾아냈습니다. Herb는 C++/CLI의 설계자 중 한 사람입니다. 이 문서(앞으로는 '설계 원리'로 부름)는 Herb의 블로그에서 찾을 수 있습니다. URL이 너무 길고 복잡하므로 검색 엔진에서 "C++/CLI Rationale"을 찾아보기 바랍니다. 제목이 말해 주듯이 이 문서는 C++/CLI에 대한 대부분의 의문에 대해 설명해 주고 있습니다. 이 문서는 “왜 C++를 확장했는가”라는 질문에서 const 함수에 대한 필자의 궁금증에 이르기까지 모든 것을 답해 줍니다. C++/CLI의 설계 배경과 근본적인 개념을 알고 싶다면 이 문서를 반드시 읽어볼 것을 권합니다. 여기서는 모두 소개할 수 없으므로 중요한 부분만 요약해서 소개하겠습니다.


일단 가장 중요한 질문, 왜 C++를 확장했는가에 대해 알아보겠습니다. 간단하고 분명한 대답은 “C++를 CLI의 중요한 언어로 사용하도록 하기 위해서”입니다. Microsoft® .NET Framework는 Windows® 개발의 미래이며 COBOL 조차도 CLI를 지원합니다. 즉, C++/CLI는 C++의 지속적인 성공을 위해 설계된 것입니다.


하지만 왜 굳이 C++를 사용할까요? ^ 또는 %와 같은 새로운 개념도 있고 ref, value, property와 같은 새 키워드도 있는 다른 언어를 확장하면 어떨까요? 사실 다른 방법은 없었습니다. '설계 원리'에서는 Bjarne Stroustrup의 말을 인용해 이러한 질문에 대답하고 있습니다. "우리가 필요한 거의 모든 개념은 기본 속에서 찾을 수 있습니다. 라이브러리를 사용하는 방식이 정말로 실현 불가능할 경우에만 언어 확장 방식을 사용해야 합니다."


평범한 C++ 코드의 경우 CLI를 대상으로 하는 것은 다른 프로세서를 위한 컴파일러를 만드는 것과 같습니다. 여기까지는 문제가 없으나 CLI는 특별한 코드 생성이 필요한 새로운 개념을 도입했으며 이는 C++에서 간단히 표현할 수 있는 것이 아닙니다. 예를 들어 속성에는 특별한 메타데이터가 필요합니다. 라이브러리나 템플릿 없이 속성을 구현할 수는 없습니다. '설계 원리'에서는 속성을 비롯하여 다른 CLI 기능을 대체할 수 있는 몇 가지 구문을 소개하고 있으며, 이러한 구문이 결국 왜 사용될 수 없었는지에 대해서도 설명하고 있습니다.

 

Managed Extensions의 쇠퇴


'설계 원리'에서는 또한 Microsoft에서 Managed Extensions를 더 이상 사용하지 않기로 결정한 이유에 대해서도 설명하고 있습니다. Managed Extensions에서 관리된 개체와 네이티브 개체 모두에 *를 사용한 것은 C++와 CLI를 통합하기 위한 영리하고 용감한 시도였지만, 참조와 네이티브 개체의 중요한 차이점이 분명치 않았습니다. 이러한 두 종류의 포인터는 같아 보이지만 동작은 다릅니다. 예를 들어 소멸 구문, 복사 생성자, 생성자/소멸자 내에서의 가상 호출 등이 모두 포인터가 가리키는 개체가 무엇인지에 따라 다르게 동작하며 이는 끔찍한 일입니다. '설계 원리'에서는 "불필요한 차이점을 감추는 것도 중요하지만 필요한 차이점은 반드시 공개해야 한다.”고 설명하면서 다시 Bjarne의 말을 인용하고 있습니다. "중요한 작업은 반드시 눈에 띄어야 합니다." 네이티브 클래스와 관리되는 클래스는 근본적으로 다른 것이므로 무시하기 보다는 그 차이점을 부각시키는 것이 나은 방법일 것입니다. 이를 위해 여러 가지 메커니즘이 고안되고 버려졌으며, 결국 C++/CLI 팀은 gcnew, ^(핸들) 및 %(참조 추적)와 같은 개념을 도입했습니다. 이렇게 관리되는 클래스와 네이티브 클래스를 분리하면 뜻밖의 효과도 누릴 수 있습니다. 예를 들어 gcnew 연산자를 사용하여 관리되는 개체를 할당하면 언젠가 관리되는 힙에서 네이티브 클래스가 할당되고, 그 반대 방향의 작업도 가능할 수 있다는 가능성을 열어두게 됩니다.


Managed Extensions는 왜 __gc나 __value와 같이 보기 흉한 밑줄 키워드를 사용하는지 궁금했던 적이 있습니까? 이는 Managed Extensions가 C++ 표준을 엄격하게 따르기 때문입니다. C++ 표준에서는 새 키워드가 필요하다면 이름 앞에 밑줄 두 개를 붙이라고 지정하고 있습니다. 꼭 그래야 할까요? Microsoft에서 __gc라는 키워드를 도입했을 때, __에 대해 프로그래머들은 강력한 항의를 보냈습니다. 뭉치면 못할 것이 없습니다. 밑줄 문자 밖에는 잃을 것도 없습니다. 밑줄을 사용하면 코드를 읽기 어려울뿐더러 마치 어셈블리 프로그램과 같이 난해하게 보이기도 합니다. 결국 C++/CLI에는 밑줄이 없는 ref 및 value가 추가되었습니다. C++에 새 키워드를 추가한 셈이지만 표준을 따르지 않아도 문제될 것은 없습니다. Bjarne은 이렇게 말합니다. "제 경험에 따르면 사람들은 자신이 고안한 매우 복잡하고 어려운 개념을 사용하기 위해 새 키워드를 만드는 것을 지나치게 좋아합니다. 그 결과, 점차 새로운 키워드들은 우리가 흔히 사용하는 용어와는 전혀 다르게 변해가고 있습니다." 맞는 말입니다. 필자는 프로그래밍에 대한 Bjarne의 심리학적 설명을 매우 좋아합니다. C++/CLI에서 밑줄이 사라진 이유는 이것입니다. 예약된 키워드가 아닌 전후 관계에 따라 사용되는 키워드를 만듦으로써 이미 이 키워드를 변수나 함수 이름으로 사용하는 프로그램과의 충돌 문제도 방지할 수 있습니다.

 

궁금증이 많은 사람이라면 밑줄을 없애는 과정에서 gc가 어떻게 ref로 바뀌었는지 궁금할 수도 있습니다. '설계 원리'에서는 관리되는 클래스가 관리되는(가비지가 수집되는) 힙에 있다는 것이 중요한 것이 아니라 그 참조 구문이 중요하다고 합니다. 핸들(^)이 포인터가 아닌 참조처럼 사용되는 것도 같은 원리입니다. 이와 같이 '설계 원리'를 읽어보면 모든 것이 분명해집니다.


분명한 차이점을 드러내는 것이 중요하다면 그렇지 않은 것을 감추는 것도 중요합니다. 예를 들어 모든 연산자 오버로딩은 개체가 네이티브인지, ref인지, 또는 value인지에 관계없이 C++ 프로그래머가 예상하는 그대로 작동합니다. C++/CLI 문서에서 차이에 대해 설명한 또 하나의 예로 다음 코드를 보겠습니다.

 

// ref class R as local variable
void f()
{ 
   R r; // ref class on stack???
   r.DoSomething();
   // ...
}

여기서 r은 스택 개체처럼 보이지만 누구라도 관리되는 클래스는 스택에 물리적으로 넣을 수 없다는 것을 알 것입니다. 관리되는 클래스는 관리되는 힙에 할당해야 합니다. 그렇다면 무슨 일이 벌어질까요? 컴파일러는 이 코드를 다음과 같은 의미로 해석하게 됩니다.

// how the compiler sees it.
void f()
{ 
   R^ r = gcnew R; // allocate on gc heap
   try
   {
      r->DoSomething();
      ...
   }
   finally
   {
      delete r;
   }
}

 

결과적으로 개체는 실제 스택에 할당되지 않습니다. 여기서 중요한 것은 로컬 변수 구문이 모든 C++ 프로그래머가 예상하는 방식으로 작동한다는 점입니다. 특히 f를 벗어나기 전에 r의 소멸자가 호출되는 것은 C++/CLI에서 결정적 소멸을 복원한 이유와 같은 이유로 설명할 수 있습니다. 소멸을 위해 모든 C++ 프로그래머가 알고 사용하는 것과 동일한 구문을 따르고 있다는 것입니다. 비결정적 소멸은 Managed Extensions의 기능 중 최악의 것으로, C++/CLI는 이 문제를 해결하기 위해 소멸자를 Dispose에 매핑하고 종료자를 위한 특별한 구문인 !를 도입했습니다. 참조 개체가 사용하는 메모리는 가비지 수집기가 활동하기까지는 그대로 남아있게 되지만 그리 큰 문제는 아닙니다. C++ 프로그래머에게는 필요할 때 소멸자가 실행되는 것이 중요하지, 개체가 파괴될 때 메모리를 회수하는 것이 중요하지는 않습니다. C++ 프로그래머는 파일 핸들, 데이터베이스 잠금과 같이 메모리 리소스가 아닌 개체를 초기화/해제하는 데 생성/소멸 패턴을 자주 사용합니다. C++/CLI를 사용하면 참조와 네이티브 클래스에 대해 여러분이 기대하는 방식 그대로 친숙한 생성/소멸 패턴을 사용할 수 있습니다. 결국 이와 같은 이유로 인해 Microsoft는 Managed Extensions의 문제를 인식하고 이를 수정하는 작업을 포기하게 된 것입니다.


미래에 대한 기대


'설계 원리'의 흥미로운 단원 중에 "Future Unifications(미래의 통합)"이라는 부분이 있습니다. 이 단원에서는 C++/CLI가 미래에 어떤 방향으로 발전할지에 대해 약간의 힌트를 주고 있는데, 예를 들어 지금은 관리되는 클래스에서 네이티브 클래스를 파생할 수 없고 그 반대로도 마찬가지지만 “기본” 클래스를 데이터 멤버로 추가하고 컨테이너 인스턴스를 호출하는 것만 담당하는 통과 래퍼를 만들면 같은 결과를 만드는 해결책을 구현할 수 있습니다. 아주 좋은 방법으로 보이며 컴파일러가 이러한 작업을 지원하지 못할 이유가 없어 보입니다. 컴파일러는 모든 CLI 부분을 포함하는 하나의 CLI 개체와 모든 C++ 부분을 포함하는 하나의 C++ 개체로 구성된 혼합된 개체를 만들어 사용할 수 있을 것입니다.


이에 대한 흥미로운 일화도 소개되어 있습니다. '설계 원리'의 저자가 이러한 혼합 클래스에 대한 아이디어를 Bjarne Stroustrup에게 처음 보여주었을 때, Bjarne은 서재로 가서 책을 펴 보여주면서 “C++에서 개체를 단일 메모리 블록에 연속해 저장할 필요는 없다.”고 말했다고 합니다. 이때까지 누구도 비연속적인 개체의 이점을 알지 못했으며 .NET과 CLI가 개발될 것이라고 예상하지도 못했습니다. 비연속이라는 문을 열어야 한다는 Bjarne의 고집이 결국 혼합된 개체를 가능하게 만든 것입니다. C++/CLI의 나중 버전에서 이러한 기능을 보게 되도 놀라지 마십시오. 여기서 주는 교훈은 여러분이 새 언어나 복잡한 프로그램을 설계하여 계속 사용될 것으로 기대한다면 단지 약간의 편의를 위해 절대 불필요한 가정을 해서는 안 된다는 것입니다.


이 밖에도 '설계 원리'에서는 재미있는 몇 가지 사실도 소개하고 있습니다. Microsoft가 C++/CLI의 원래 내부 이름으로 사용한 것은 MC^2였다고 합니다. M은 “관리되는”의 의미, C는 C++를 의미하며 ^2는 앨버트 아인슈타인의 공식에서 차용한 것입니다. 하지만 결국 이름이 너무 장난스럽다는 이유로 채택되지 못했습니다. 필자도 동의하는 부분입니다. MC^2라는 이름을 그대로 사용했다면 아마도 받아들이기 힘들었을 것입니다. 이름을 C++/CLI로 결정한 데는 Bjarne이 C++의 이름에 대해 말한 것과 같은 이유가 있었습니다. Bjarne은 "이름을 C++라고 정한 것은 짧고, 쉽게 해석이 가능하며 ‘부수적인 C’와 같은 형식이 아니었기 때문입니다”라고 말했습니다. C++/CLI 역시 C++를 먼저 넣고, "부수적인 C++"라는 표현을 피한 것뿐입니다.


'설계 원리'에서는 속성, gcnew, 제네릭 및 const 등의 다른 C++/CLI 확장 기능에 대한 설명과 더불어 마무리에는 유용한 질문과 대답 단원을 소개하고 있습니다. 자세한 내용은 '설계 원리'를 다운로드하여 읽어보십시오. Const에 대해 다시 얘기해 보겠습니다. C++/CLI는 왜 const 데이터는 허용하면서 const 함수는 허용하지 않는 것일까요? 간단히 얘기하면 CLI는 modopt/modreq를 함수에 직접 넣는 것을 허용하지 않기 때문입니다. 이 정보를 메타데이터에 인코딩하는 방법이 있기는 하지만, 아직 테스트되지 않았습니다. 그리고 '설계 원리'에서는 언젠가 이러한 기능이 추가될 것이라고 조심스럽게 시사하고 있습니다.


프로그래밍의 진화


C++/CLI는 C++를 CLI의 중요한 언어로 만들었으며 '설계 원리'를 읽어보면 이러한 결정에 대해 작은 의심도 없었음을 알 수 있습니다. C++는 아직도 시스템 프로그래밍 분야에서 최고의 언어이며, 이는 다른 어떤 언어보다도 CLI에 직접적으로 액세스할 수 있고 아직까지도 널리 사용되는 예전 Win32® API를 호출해야 할 경우 C로도 확장될 수 있기 때문입니다.


C++/CLI가 얼마나 중요하며 무엇을 나타내는지 이해하기 위해서는 현재 우리가 프로그래밍의 진화 단계에 어느 지점에 있는지 생각해 보아야 합니다. 간단하게 이러한 내용에 대해 살펴보겠습니다. 예전에는 프로그래머가 토글 스위치를 사용하여 프로그램을 작성했습니다. 여기서 발전한 것이 종이 테이프였고, 각 컴퓨터가 고유한 “기계” 언어를 가지는 단계로 발전했습니다. 컴퓨터가 진화함에 따라 프로그래머도 이러한 새 기계를 대상으로 하는 프로그램을 만들어야 했고, FORTRAN, BASIC, C와 같은 고급 언어가 개발되었으며 고급 언어를 각 컴퓨터에 대한 명령으로 변환해 주는 “컴파일러”가 사용되기 시작했습니다. 그림 2에서 이러한 과정을 보여 줍니다. 이제 프로그램을 만들어 컴파일하면 다른 컴퓨터에서 쓸 수 있게 된 것입니다. C가 시스템 프로그래밍을 위한 최적의 언어로 선택된 이유는 “고급 언어 중 가장 저급 언어”였기 때문입니다. 이는 사람이 사용할 수 있는 언어 중 가장 기계와 친숙한 언어라는 의미입니다. 근래에 사용되는 대부분의 운영 체제는 C로 작성되었으며 성능이 중요하고 하드웨어 조작이 필요한 일부분만 어셈블리 언어로 코딩되어 있습니다.


오랜 세월 후에 C를 개선하여 개체 지향 방식 등 많은 새로운 기능을 도입한 C++가 등장했습니다. Bjarne은 이렇게 말했습니다. "C++는 저자나 그의 친구들이 어셈블러, C 또는 다양한 근래의 고급 언어를 사용해 프로그래밍할 필요가 없도록 하기 위해 설계되었습니다. C++의 주 목적은 모든 프로그래머가 좋은 프로그램을 편하고 즐겁게 작성할 수 있도록 하는 것입니다." C++는 훌륭한 언어이지만, 고급 언어는 서로 호환되지 않는 경우가 많습니다. C++에서 코드를 작성하면 이를 BASIC과 같은 다른 언어에서 사용할 수 없으며, 가능하다 해도 상당한 어려움이 따릅니다. 각 언어는 각자 고유한 영역 내에서 처리되기 때문입니다. 이러한 특징은 독립 실행형 응용 프로그램에는 문제가 없지만 응용 프로그램이 보다 복잡해지고 환경이 분산되면서 공유 코드에 대한 필요성이 대두되기 시작했습니다. 결국 프로그래머는 완벽히 캡슐화되어 재사용이 가능한 구성 요소를 원하게 된 것입니다. 이러한 구성 요소를 사용하면 각 조각을 만들어 결합하는 것으로 응용 프로그램을 만들 수 있을 것이며 모든 조각이 같은 언어로 작성될 필요도 없을 것입니다.


이러한 다양한 구성 요소를 통합하려는 시도는 몇 년에 걸쳐 진행되었습니다. 처음에는 C 런타임이나 printf와 같은 라이브러리를 사용한 언어가 등장했고, Windows가 사용되면서 메모리 절약을 위한 DLL의 지연 로딩(DLL에 Dynamic이란 이름이 사용된 이유임)이 제공되었습니다. 또한 Visual Basic이나 COBOL과 같은 언어에서 가져오기 구문을 사용하여 컴파일러가 C와 연계된 호출을 DLL에 보내는 방식으로 DLL 사용이 가능해짐으로써 언어의 상호 운용성이 증대되는 효과가 있었습니다. 하지만 응용 프로그램과 DLL의 연결은 너무 강했으며 부서지기도 쉬웠습니다. 각 응용 프로그램은 DLL의 각 항목에 대한 이름과 서명을 알아야 했고 DLL에서 응용 프로그램으로의 호출은 함수 포인터를 콜백으로 전달해야 했으므로 상당히 귀찮은 일이었습니다. 때문에 프로그래머들이 VBX를 개발했고, 이 것이 OCX를 거쳐 COM으로 발전했습니다. 다행히도 COM은 언어 중립적인 것으로, COM에는 “형식 라이브러리”가 있어 연결 시 함수 이름을 알 필요가 없고 런타임에 문의하는 방식이 가능했습니다. COM은 상당히 유용하지만 프로그래밍이 매우 어렵다는 단점이 있습니다. 아이러니하게도 C++에 기반을 두고 있으면서도 C++에서 프로그래밍하기가 가장 어렵습니다. COM에는 다른 문제도 있습니다. 너무 저급 언어이며 보안이나 메모리 관리에 대한 기능이 빈약하다는 것입니다.


최종 목표


현재는 2007년이며 우리에게는 .NET Framework와 그 표준 부속물인 CLI가 있습니다. CLI는 프로그래밍 언어와 컴퓨터 사이에 새로운 추상 계층을 삽입하여 재사용성 문제를 완전히 다른 방법으로 해결하였습니다. 이제 시스템 명령을 생성하는 대신 컴파일러는 MSIL 코드를 생성하며 CLI 가상 시스템/JIT(just-in-time) 컴파일러가 이를 즉시 기계어 코드로 컴파일합니다. 가상 시스템(Virtual Machine, VES 또는 Virtual Execution System)은 컴퓨터를 위한 추상 계층을 제공합니다. 가상 시스템은 새로운 개념이 아니라 사실 오랫동안 사용되어 왔습니다. Pascal이나 ZIL(필자가 한때 몸담았던 Infocom이란 회사에서 게임 개발을 위해 내부적으로 사용하던 언어, Zork Implementation Language의 약자임)과 같은 언어는 고급 언어를 P-코드(또는 Z-코드)로 컴파일하여 가상 시스템에서 해석하는 방식을 이미 사용하고 있었습니다. 하지만 CLI는 모든 언어가 사용할 수 있는 공용 가상 시스템(CLI에서 C가 의미하는 부분)을 제공한다는 점이 다릅니다. CLI는 클래스, 속성, 상속성, 리플렉션과 같은 기본적인 개념을 지원합니다. VES/VM는 메모리 관리와 보안 기능도 제공하므로 프로그래머는 악의적인 바이러스에 문을 열어 주는 버퍼 오버런이나 기타 버그를 걱정하지 않아도 됩니다. .NET Framework와 CLI가 널리 사용되면서 Visual Basic, Fortran, COBOL, C#과 같은 고급 언어는 점차 그 경계가 사라지는 분위기이며, 클래스, 상속성, 멤버 함수 등의 CLI 기반 개념을 지원해야 하기 때문에 C++ 역시 그 영향을 받고 있습니다. 각 언어는 여전히 독자적인 영역을 가지고 있으므로 프로그래머가 자신의 도구를 .NET Framework을 사용하도록 바꿀 필요는 없으며 몇 가지 새로운 개념만 배우면 됩니다.


이제 프로그래머는 원하는 언어를 선택하여 클래스를 작성할 수 있으며 언어에 관계없이 다른 프로그래머가 작성한 클래스를 사용할 수도 있습니다. 어떤 언어를 사용해도 모든 구성 요소를 프로그래밍할 수 있고, 약간의 프로그래밍 노력만 거치면 모든 구성 요소가 매끄럽게 서로 연결됩니다. 또한 CLI의 보안, 가비지 수집 등 인프라 기능(CLI에서 I가 의미하는 부분)의 혜택을 받을 수 있습니다. 이후에 Microsoft에서 새로운 CLI 기능을 추가하면 모든 언어가 그 혜택을 받을 수 있을 것입니다. Windows Vista™와 .NET Framework 3.0(10,000개의 새 클래스와 더불어 Windows Presentation Foundation, Windows Communication Foundation, Windows Workflow Foundation 및 Windows CardSpace™와 같은 새로운 기술이 연계되어 있음)이 개발되면서 Windows는 CLI 클래스로서 다시 만들어지고 있습니다. 이제는 재사용 가능하고, 언어 중립적이며 상호 운용이 가능한 구성 요소라는 목표에 도달한 것으로 보입니다. 이는 매우 큰 패러다임의 변화로, 전진적인 진화를 거쳐 놀라운 수준에 이른 것입니다. 이제는 프로그래밍이 아주 쉬워지고 있습니다.


이러한 모든 사항을 곰곰이 생각했을 때 C++가 새로운 세계에 적응하는 것은 당연한 일로 생각됩니다. C++/CLI이 등장한 이유가 바로 이것입니다. C++/CLI가 없다면 C++는 Windows 프로그램에 사용할 수 없는 유일한 근대 프로그래밍 언어로 남았을 것입니다. 또는 점차 그 수명을 다하여 역사의 변두리로 밀려났을 수도 있습니다. 하지만 C++/CLI가 있기에 그런 일은 일어나지 않습니다. C++를 좋아하는 필자와 같은 프로그래머는 걱정 없이 계속 사용해도 됩니다. 그림 2는 프로그래밍 언어의 패러다임 변화와 그 속에서 C++가 차지하는 위치, 그리고 "/CLI"가 없다면 어떨지를 간략하게 보여 줍니다.

프로그래밍의 진화 과정

그림 2: 프로그래밍의 진화 과정 (더 크게 보려면 이미지를 클릭하십시오.)

 

작별 인사


이제 작별 인사를 하려고 합니다. 그 동안 필자가 기고해온 C++ At Work 칼럼이 이번 호를 마지막으로 여러분 곁을 떠납니다. 많은 칼럼이 중단되는 와중에서도 그 동안 꽤나 오래 이 칼럼을 기고해 온 것을 자랑스럽게 생각합니다. 칼럼이 중단되는 것은 Microsoft나 MSDN®Magazine에서 C++의 위상이 약해진 것 때문은 아니며, 14년간에 걸친 164개 칼럼(이번이 165개 째)을 기고하면서 필자가 많이 지쳤기 때문입니다. 재미있는 일화를 하나 소개하면, 편집장인 Josh Trupin은 필자를 "MSDN Magazine의 Cal Ripken"이라고 부르기도 했습니다. 필자는 야구 팬은 아니지만(축구를 더 좋아합니다) Cal Ripken이 누군지는 압니다. 그래서 Cal이 몇 경기나 출장했는지 웹에서 검색해 보았더니 2,632 경기였습니다. 그리고 그의 이력에서 "많은 팬들은 Cal이 충분히 휴식을 취했다면 더 나은 플레이어가 되었을 것이다."라고 말한 내용도 보았습니다. 필자에게도 해당되는 말이라 생각합니다. 하지만 이것이 필자가 다시는 MSDN Magazine에 기고하지 않을 것임을 의미하지는 않습니다.


칼럼을 마치면서 그 동안 필자의 많은 오류와 실수를 지적해주고 격려를 통해 힘을 준 많은 독자들에게 감사의 말을 전하고 싶습니다. 어떤 독자는 필자가 칼럼을 게시하기 전에 솔루션을 테스트하는 수고를 해주기도 했습니다. 또한 그 동안 함께 일해온 MSDN Magazine의 많은 동료들에게도 감사의 말을 전합니다. 과거에서 현재로 순서 없이 나열해보면 Steve, Josh, Joanne, Eric, Etya, Terry, Laura, Joan(두 명 모두), Nancy, Val, 그리고 Milo가 떠오릅니다. 빠진 사람이 있는지 모르겠네요. 이들은 그 동안 필자를 여러모로 많이 지원해 주었으며 다양한 분야와 내용의 집필이 가능하도록 필자에게 자유로운 공간을 허락해 주었습니다. 그 중에서도 특히 Gretchen Bilson에게 감사하고 싶습니다. 몇 년 전 이미 MSDN Magazine을 떠난 그녀는 MSDN Magazine이 Microsoft Systems Journal이던 1993년에 필자를 고용한 고마운 분입니다.


여기까지입니다. 하지만 영영 떠나는 것은 아닙니다. 아놀드 슈왈츠제네거가 말했듯이 저는 돌아올 것입니다. 즐거운 프로그래밍을 계속하시기 바랍니다.

 

Gak 자료: 다양한 질문

 

딱딱한 내용은 여기서 끝내고, 그 동안 필자가 받았던 특별하고 재미있는 몇 가지 질문에 대해 소개하면서 칼럼을 마치려 합니다. 필자는 이러한 자료를 Gak라는 폴더에 수집해 두었으며 범주별로 분리해 두었습니다. 예를 들어 언어에 대한 질문은 따로 모아 두었습니다.

 

C++를 어디서 다운로드할 수 있나요?

 

많은 사람들이 C++를 높게 평가합니다. 이유가 무엇일까요? Visual Basic이나 Delphi에서는 할 수 없지만 C++에서 할 수 있는 작업은 어떤 것이 있을까요? 이에 대해서는 필자가 많은 경험을 가지고 있습니다. Visual C++®를 사용하더라도 필요한 모든 것은 항상 찾을 수 있었습니다. 중견 프로그래머들이 이 언어를 사용하는 이유가 바로 이것입니다.

 

“중견 프로그래머”에 필자는 포함되지 않았으면 좋겠네요. 다음 질문은 많은 사람이 어려워하는 포인터에 대한 것입니다.

아직도 포인터(var, object, functional)를 잘 이해하지 못했습니다. 설명을 해 주시거나 공부할 자료를 보내 주실 수 있나요?

 

C++를 처음 배우고 있으며 포인터가 무엇이고 어떻게 사용되는지 궁금합니다. 많은 책을 보았지만 너무 복잡하게 설명되어 있습니다. 포인터란 특정한 메모리 위치를 가리키는 것으로 알고 있는데 이런 개념이 왜 필요한지 모르겠습니다. 아마도 컴퓨터가 각 위치를 자동으로 추적하려는 것일까요? 답변 부탁드립니다.

 

필자는 이 질문을 동료 필자인 Matt Pietrek과 John Robbins에게 보내어 조언을 구했습니다. Matt는 이렇게 말하더군요. "그 사람의 생각이 맞다. 포인터는 오래되어 불필요한 개념이며 이제는 배울 필요가 없다." John은 한술 더 뜨더군요. "포인터는 개 이름인줄 알았다. 뭔가 다른 의미가 있나?"

 

다음은 컴파일러에 대한 질문입니다.

 

Paul씨, 컴파일하는 동안 링크 MFC 라이브러리는 어떻게 컴파일합니까? 때로는 DLL을 컴파일하기도 합니다. 지금까지 이 소스는 컴파일하지 않았는데요. 컴파일하는 방법이나 소스를 좀 보내 주십시오. 감사합니다.

 

더 자주 받는 질문은 Windows에 대한 것입니다.

 

키보드/마우스 감지 프로그램을 만들고 있는데 문제가 있습니다. 예를 들어 “시간을 세는” 프로그램이 선택된 상태에서 작동하고 있을 때 선택이 해지된 다음에도 계속 작동하도록 하려면 어떻게 해야 할까요? 여러 가지 방법을 시도해 봤지만 실패해서 이렇게 문의 메일을 보냅니다.

 

중요한 것은, 질문에서 말하는 키보드/마우스 감지 프로그램이 무엇을 말하는 것인지 모르겠다는 점입니다. 필자는 이런 프로그램을 만들어 본 적이 없습니다. 때문에 질문의 의도도 잘 모르겠네요. 아쉬운 일입니다.
다음은 연산에 관련된 질문입니다.

 

문자를 인코딩했다가 나중에 디코딩하는 작업을 수행하는 프로그램을 만들고 있습니다. 그런데 디코딩 부분에서 % 연산을 유지해야 하기 때문에 어려운 점이 있습니다. 나누는 숫자와 나머지는 알고 있는데 이것으로는 애초에 나눈 숫자가 무엇인지 알 수 없습니다. 예를 들어 연산의 결과로 나머지가 22이고 이 연산은 (숫자)%63이었다면 이 숫자는 무엇일까요? 도움을 부탁 드립니다.

 

솔직히 어려운 점이 있다고 말한 이유를 이해할 수 없습니다. n%a=b라는 연산에서 a와 b는 아는데 n을 모르겠다는 의미 아닌가요? 수학 시간에 열심히 듣지 않았던 분인가 봅니다. 다음과 같이 가끔은 “제 숙제를 대신 해주실래요?”라는 질문도 종종 받곤 합니다.

 

프로그래밍에 대해 잘 모릅니다. 20개의 숫자를 입력하고 이를 내림차순으로 정렬해야 하는데 어떻게 해야 할까요?

 

다음 두 프로그램을 만들어야 하는데 분석을 좀 부탁드립니다. 내일 정오까지 완료해야 하는데 도와주세요!

  • 사용자의 최초 잔액과 예금 인출액을 입력 받아 사용자가 -1을 입력하거나 잔액이 0이하가 될 때까지 반복하는 프로그램을 작성하시오. 사용자의 최초 잔액, 최후 잔액, 인출 횟수와 평균 금액을 출력하시오.
  • 임금 지불 내역 프로그램을 작성하고 직원의 격주 순수 임금을 출력하시오. 직원의 근무 시간과 시간당 임금을 입력 받고 초과 근무에 대해서는 가중치를 적용해야 합니다. 공제액은 총 급여의 18%로 책정하여 계산하십시오. 사용자의 급여와 연봉을 출력하십시오.

 

세 번째 것도 있는데 생략하겠습니다. 때로는 아주 긴 소스 코드가 포함된 질문도 받곤 하는데, 읽지도 않고 지워버립니다. 또는 필자의 칼럼과 전혀 관계없는 Visual Basic, Microsoft Access™, Excel® 프로그래밍 등에 대해서도 질문을 받는 경우가 있으며 “컴퓨터가 망가졌는데 어떻게 해야 할까요?” "시작 단추를 안 누르고 컴퓨터를 끄는 방법은 없나요?"와 같은 매우 사려 깊은 질문도 간혹 있습니다. 제발 이런 질문은 Raymond Chen의 블로그에 올려 주시기 바립니다. 다음과 같이 특정한 범주로 분류하기 힘든 질문도 있습니다.

 

Paul씨, 일반적인 개발자가 하루에 작성하는 Visual C++ 코드의 평균 줄 수에 대한 통계 자료가 있나요? 도움을 바랍니다.

 

존경하는 DiLascia씨, 어떻게 하면 당신처럼 될 수 있을까요?

 

안녕하세요. 그 동안 MSDN을 많이 구매했고 거기서 당신 이름을 보았습니다. "Microsoft에 취직하려면 어떻게 해야 할까요?" 저는 Visual C++ 프로그래밍을 좋아하며 기술과 가치, 미래를 위해 Microsoft에서 일하고 싶습니다. 저는 MFC로 멀티미디어 프로그램을 만들 수 있으며 학교 성적도 좋은 편입니다. 그러나 영어 실력은 그저 그렇습니다. 프로그래밍이 너무 재미있어서 5년간 여자 친구도 사귀지 않았습니다. 엉뚱한 질문이라 생각하실지 모르지만 답장을 주셨으면 좋겠습니다. Microsoft에서 일하려면 어떻게 해야 하는지 알려 주십시오. 감사합니다.

 

영어 실력은 그저 그렇지만 무엇보다도 이 청년의 열정적인 자세에 박수를 보내고 싶습니다. 필자는 “죄송합니다. 모르겠네요.”라고 보낼지라도 모든 질문에 대답하려 노력합니다. 실제로 필자가 답변을 보내면 놀라는 독자들이 많았습니다.

 

Paul씨, 당신 같은 유명한 저자가 모르는 사람을 지속적으로 도와주리라고는 생각지 못했습니다. 당신은 지식이 뛰어난 전문가일 뿐만 아니라 아주 좋은 사람이군요. 감사합니다.

 

저 역시 감사합니다. 마지막으로 재미있는 질문 하나를 소개합니다.

 

Windows 프로그래밍에서 심령의 창 (Psychic Window)이란 무엇인지요? 철자를 정확히 모르겠네요. 친구가 물어본 것이라서요. 부탁 드립니다.

 

이 질문에 대한 대답은 찾을 수 없었습니다. 심령의 창을 찾으신다면 초능력자에게 물어보시는 것이 나을 것 같네요. 누구 아시는 분이 있으면 필자에게 텔레파시를 보내 주십시오.

 

저자 소개


Paul DiLascia는 프리랜서 소프트웨어 컨설턴트이자 저명한 웹/UI 디자이너입니다. 저서로는 Windows++: Writing Reusable Windows Code in C++(Addison-Wesley, 1992)가 있습니다. Paul은 여가 시간을 활용해 MFC 클래스 라이브러리인 PixieLib을 만들어 그의 웹 사이트인 www.dilascia.com에 공개하고 있습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

  1. 뭐가 뭔지 ㅠㅠ;; C계열은 다 어려워요 ㅠㅠ

    2010.01.25 17:04 [ ADDR : EDIT/ DEL : REPLY ]
    • C++/CLI 역시 닷넷 프레임워크에서 사용할 수 있는 일반적인 프로그래밍 언어로 보고 개인적으로 많은 관심을 두고 있던 중에 찾게 된 기사라서 퍼오게 되었습니다. 궁금하신 점은 언제든 질문해 주세요. :-)

      2010.01.25 19:39 [ ADDR : EDIT/ DEL ]
  2. ㅇㅅㅇ 저는 C++는 그냥 C++쓰지 .net이랑 짬뽕된 C++/CLI는 좀 안땡기더군요.
    이왕 할거면 첨부터 .net을 위해 설계된 C#이 젤 잘맞는듯해요.
    역시 플랫폼에 맞춰 설계된 언어를 쓰는게 최고인듯. =ㅅ=

    2010.01.25 20:58 [ ADDR : EDIT/ DEL : REPLY ]
    • C++/CLI는 닷넷 프레임워크를 활용하기 위한 하나의 도구에 지나지 않습니다. C++과 COM 기술만을 이용하여 닷넷 프레임워크를 호스팅 하는 방법도 있으니 이 또한 좋은 선택이 될 수 있을 것 같습니다.

      2010.01.26 00:06 [ ADDR : EDIT/ DEL ]
  3. 음... 모르겟어~!!ㅠㅠ 역시 초짜... 이래서야... 게임업체 취직이나 가능할려나...

    2010.01.25 21:56 [ ADDR : EDIT/ DEL : REPLY ]
    • 고급 주제에 대한 매거진 아티클이니 너무 신경쓰지 않으셨으면 합니다. ㅎㅎ

      2010.01.26 00:06 [ ADDR : EDIT/ DEL ]

포트폴리오2009. 11. 5. 01:09

다음에 나열된 코드는 xPlatform의 msvcrt 모듈을 활용하여 ANSI, 유니코드 인코딩 아래에서 문자열의 길이를 측정하는 샘플 코드입니다.

 

using System;
using xPlatform;
using xPlatform.x86.msvcrt;

namespace xPlatformSample
{
    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                Console.WriteLine("측정할 문자열을 입력하고 Enter를, 종료하려면 입력없이 Enter를 누르세요.");
                Console.Write(">> ");
                string input = Console.ReadLine();

                if (input.Length < 1)
                    break;

                Console.WriteLine();
                Console.WriteLine("ANSI Length (strlen): {0} Byte(s)", msvcrt.strlen(input));
                Console.WriteLine("Unicode Length (wcslen): {0} Char(s)", msvcrt.wcslen(input));
                Console.WriteLine();
            }
        }
    }
}

 

실행 결과

 

 

xPlatform 다운로드: http://blendxplatform.codeplex.com/

 

xPlatform 활용 예제는 계속 업로드될 예정입니다. xPlatform을 활용하는 예제들 중 필요한 것이 있으면 요청에 따라 예제 코드를 만들어서 공개할 수 있으니 많은 참여 부탁드립니다. :-)

 

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

포트폴리오2009. 11. 1. 02:40

긴 여정 끝에, Project Blend: xPlatform의 2009년 11월 릴리즈를 공개하게 되었습니다. Project Blend: xPlatform (이하 xPlatform)은 .NET Framework 2.0 이상의 환경에서, C#이 아닌 다른 프로그래밍 언어들 (예: Visual Basic .NET, Visual J#, Iron Python 등)을 위한 비관리 프로그래밍 기술을 제공하고, 운영 체제에 대한 API를 제공하기 위하여 시작된 프로젝트입니다.

 

다운로드 링크

http://blendxplatform.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=35207

 

xPlatform 프로젝트는 Ms-PL (Microsoft Permissive License) 아래에서 배포되는 오픈 소스 기반 소프트웨어입니다. 그리고 아직까지는 일반 개발 환경에 직접 투입하기에 적절하지 않을 수 있음을 미리 알려드리며, 정식으로 릴리즈가 되기 이전까지는 많은 피드백과 테스트가 필요합니다.

 

다음의 코드는 실제로 xPlatform의 Core 라이브러리를 사용하여 작성한 샘플 코드로, 비 관리 영역 상의 메모리를 Unsafe 코드를 사용하지 않는 C#을 통하여 자유롭게 제어하는 예시를 담고 있습니다.

 

using System;
using xPlatform;
using xPlatform.Buffers;

class Program
{
    static void Main()
    {
        int Length = 15;

        using (GlobalHeapBuffer<double> myBuffer = new GlobalHeapBuffer<double>(Length))
        {
            Pointer<double> ptr = myBuffer.TypedPointer;

            for (int i = 0; i < Length; i++, ptr++)
                ptr.SetData(i * 0.2);

            ptr = myBuffer.Address;

            for (int i = 0; i < Length; i++)
            {
                Console.WriteLine(">> ptr[i]: {0}", ptr[i]);
                Console.WriteLine(">> (ptr+i).GetData(): {0}", (ptr + i).GetData());
                Console.WriteLine(">> (ptr+i)[0]: {0}", (ptr + i)[0]);
                Console.WriteLine(">> ptr.GetData(i): {0}", ptr.GetData(i));
                Console.WriteLine();
            }

            ptr = myBuffer.Address;

            for (int i = 0; i < Length; i++)
                Console.WriteLine(">> ptr++[i]: {0}", ptr++[0]);

            ptr = myBuffer.Address;

            for (int i = 0; i < Length - 1; i++)
                Console.WriteLine(">> (++ptr)[i]: {0}", (++ptr)[0]);
        }

        Console.ReadLine();
    }
}

 

릴리즈를 다운로드하여 설치를 마무리하면, Visual Studio 및 Visual Studio Express Edition의 프로젝트 참조 추가 대화 상자에서 다음과 같이 xPlatform 프로젝트에 대한 참조가 나타납니다. 현재 배포되고 있는 이들 항목들에 대한 설명을 드리면 다음과 같습니다.

 

 

xPlatform Core에는 형식화된 포인터, 메모리 버퍼, 문자열 버퍼, 비트 연산 관련 보조 루틴 등이 포함되어있으며, ModuleBase 클래스를 통하여 API 모음에 대한 서비스를 제공하게 될 것입니다. 별도의 예외 사항이 없는 한, API 묶음들은 xPlatform Core에서 제공하는 추상 클래스 ModuleBase 클래스를 상속받게 됩니다.

 

xPlatform kernel32 (x86)과 xPlatform msvcrt (x86)은 이번 릴리즈에서 공개하는 API 모음입니다. kernel32.dll과 msvcrt.dll에 대한 P/Invoke 호출들을 제공하므로 단지 이들 어셈블리를 프로젝트에 추가하고, 호출하기만 하면 됩니다.

 

아직 이 프로젝트가 가야 할 길이 멀고, 분명히 문제점이 있을 것입니다. 이러한 부분들을 피드백으로서 제 메일 (rkttu nospam rkttu dot com) 앞으로 보내주시거나, 가급적 http://blendxplatform.codeplex.com/ 에 접속하셔서 여기서 이용하실 수 있는 이슈 트래커에 올려주시면 최대한 반영할 수 있도록 하겠습니다.

 

더불어서, 프로젝트에 개발자, 코디네이터로 참여해주실 분이나, 후원해주실 분들도 언제든지 환영합니다. :-)

 

다운로드 링크

http://blendxplatform.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=35207

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Windows + .NET2009. 9. 14. 10:19

ASP.NET 2.0 이후로는 코드 비하인드에서 주로 사용하는 C# 언어 말고도 동시에 Visual Basic .NET, C++ CLR, JScript.NET 등의 프로그래밍 언어를 사용할 수 있습니다. 그러나 App_Code 폴더의 경우 동시에 여러 프로그래밍 언어를 사용하여 컴파일하려고 할 경우 아래와 같은 오류 메시지를 만나게 됩니다.

위와 같은 오류가 발생하였을 경우 어떻게 처리하면 좋을까요? 이 때에는 App_Code 밑에 별도의 분리된 Sub Directory를 구축하여 언어 별로 달리 구성하는 것이 가능합니다.

web.config 파일에서 <system.web> 요소 아래에 <codeSubDirectories> 컬렉션 요소에 별도로 구분하고 싶은 서브 디렉터리의 이름을 지정하고, 솔루션 탐색기의 디렉터리 구조에서처럼 App_Code 폴더 밑에 같은 이름의 디렉터리를 생성하여, 여기에 다른 프로그래밍 언어의 코드를 지정해두면 설정은 끝납니다.

이렇게 변경함으로서, App_Code 폴더의 코드는 C#만을, App_Code 폴더 내의 SubDir 폴더의 코드는 VB.NET만을 사용하면서도, 단일 웹 사이트 내에 모두 연결되는 어셈블리들이기 때문에 Public으로 노출하는 어셈블리들은 프로젝트에서 사용이 가능합니다. 만약 Reflection을 활용해야 하는 경우 주지해야 할 것이 하나 있는데 서브 디렉터리로 분리한 경우 이것은 App_Code라는 어셈블리와는 또 다른 별개의 어셈블리가 된다는 점입니다. 같은 방법으로 Phalanger (PHP의 .NET Framework 구현), JScript.NET, IronPython, C++ CLR 등의 코드를 쉽게 ASP.NET 사이트 안으로 통합할 수 있습니다.

동적으로 생성되는 어셈블리임을 감안하여 Assembly에 적용할 수 있는 Attribute를 사용하여 식별이 편리하도록 구성하면 Reflection을 필요로 하는 경우 도움이 될 수 있습니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Visual C++2009. 6. 21. 22:06

닷넷 프레임워크 기술들 중 가장 적게 알려지고 그 비중이 많이 축소되어 소개되는 부문이 바로 Visual C++ CLR일 것입니다. 생각보다 C++ CLR이 유용할 수 있음에도 불구하고 여론에 떠밀려서 거의 사장되다시피하고 있지요. 이번 블로그 포스트에서는 C++ CLR을 통해서 실용적인 코딩 하나를 해볼까합니다.

C++과 더불어 관련 라이브러리들 (STL, ATL, WTL, Boost, MFC 등)의 경우 일반적인 응용프로그램을 작성하거나, 성능 튜닝이 필요한 응용프로그램들을 작성하거나, 수학 라이브러리 등의 힘을 빌어 불필요한 오버헤드가 없는 고속 연산을 처리하는 등의 목적에 알맞게 디자인되어있습니다. 그러나 엔터프라이즈 프로그래밍의 경우에서처럼 구조화된 처리를 수행해야 하는 경우 상당히 불편한 점이 많습니다. 간단한 예로 당장 XML 문서 하나 분석하는 것도 썩 편리하지는 않지요.

Visual Studio 패밀리에서 공식적으로 제공되는 기능은 아니지만 C++ CLR도 닷넷 프레임워크 위에서 기동되는 어셈블리를 작성할 수 있습니다. 그리고 더 중요한 것은 기존의 x86 코드나 x64 코드를 MSIL 어셈블리 사이에 끼워넣을 수 있다는 점입니다. 이러한 사실을 바탕으로 하여 하이브리드 코드를 만들 수 있습니다.

그럼 하나씩 살펴보도록 하겠습니다.

1. C++ CLR 기반의 클래스 라이브러리 프로젝트 하나를 만듭니다. 프로젝트 이름으로 여기서는 "CLRxASPX"를 사용하기로 하겠습니다.

2. 여느 닷넷 프로젝트처럼 예상 가능한 종류의 파일들이 만들어집니다. AssemblyInfo.cpp 파일은 어셈블리 어트리뷰트를 정의하는 부분으로 다음과 같이 코드가 구성되어있습니다.

C#에서와 마찬가지인 어트리뷰트 사용법입니다. 다만 C++ 컴파일러의 특성상 空문장임을 뒷쪽에 명시해둔 것이 다른 부분이라고 할 수 있겠습니다. 그리고 네임스페이스의 참조 방법이 C#과 동일하게 되어있습니다. C#에서 흔히 사용하는 using은 C++의 using namespace와 같습니다. 그리고 C++에서 흔히 사용하는 using std::cout; 같은 참조는 C#에서는 using Console = System.Console; 과 같이 표현이 가능합니다.

특이한 점이 하나 더 있다면 stdafx.h의 존재입니다. MFC나 ATL 프로젝트에서 Precompiled Header라는 명목으로 많이 사용되던 것이 C++ CLR에도 그대로 적용된 걸 볼 수 있습니다. 거리낌없이 그 개념 그대로 stdafx.h에 Windows API 헤더를 추가하거나 프로젝트 전반에 걸쳐 사용하고 싶은 다른 라이브러리의 헤더를 추가하면 됩니다.

그럼 stdafx.h는 어떻게 구성되어있는지 한 번 살펴보도록 하겠습니다.

C++ CLR의 유용함이 느껴지는 부분입니다. 굵게 표시한 부분이 예제를 위하여 추가된 코드로, Win32 API 헤더를 추가한 것입니다. WIN32_LEAN_AND_MEAN은 컴파일러나 링커의 처리를 최소화하기 위한 것으로 통계적으로 사용 확률이 그닥 높지 않은 코드, 라이브러리를 사전에 제거해주는 옵션입니다. 예제에서는 API 참조를 위해서만 stdafx.h를 이용한 것이므로 stdafx.cpp에는 다른 서술이 되어있지 않아서 생략합니다.

이제 실제 코드를 살펴보기로 합니다.

using namespace로 모든 네임스페이스의 요소들을 참조할 수도 있지만  필요한 항목들만 위와 같이 참조할 수도 있습니다. 그리고 아래의 클래스 선언을 보면 일반 C++ 클래스 선언과는 구별되는 내용들이 몇 가지 있습니다. 우선, class 키워드 앞에 ref 키워드가 사용된 걸 볼 수 있는데 이것이 이 클래스가 Managed Class 임을 나타내는 것입니다. 그 다음에는 상속 대상을 ASP.NET의 페이지 클래스로 정한 것이 보입니다.

Protected 멤버 메서드로 Page_Load 메서드가 선언된 것이 보입니다. 이 때 알아둘 것이 있는데 ASP.NET은 내부적으로 Reflection을 통해서 실제로 Page 클래스의 Load 이벤트에 추가한 이벤트 처리기가 아니라도 자동으로 이름을 통하여 호출 대상을 결정하기 때문에 위의 메서드는 항상 실행됩니다.

그리고 C++ CLR에서 닷넷 프레임워크의 형식들을 이용할 때에는 닷넷 프레임워크 상의 관리되는 참조 객체임을 표현하기 위하여 과거의 Managed Extensions for C++ 시절때 사용하였던 __gc * 형식 대신 ^ 기호를 사용합니다. 포인터의 * 와는 구분되는 것으로 주소값을 얻기 위한 형변환 시도는 허용되지 않습니다. 이렇게 사용되는 형변환은 주소값에 대한 형변환이 아니라 형식 자체에 대한 형변환 시도가 됩니다. 별도로 해당 형식이 암묵적/명시적 형변환 연산자를 가지고 있지 않을 경우 상속 관계와는 무관하므로 컴파일이 실패합니다. 참고로, Page_Load 메서드가 이벤트 핸들러로서의 조건을 충족하려면 반환 형식은 void, 즉 반환 대상이 없으며, 두 개의 매개 변수를 받아들여야 합니다. 하나는 이벤트를 발행한 출처의 참조, 또 하나는 이벤트 인자 개체의 참조입니다. 자세한 내용은 System::EventHandler 대리자를 참고하시면 됩니다.

구현하기 나름이지만, 원래의 C++ 코드 스타일을 유지하기 위하여 선언부와 구현부를 나눈다면 위와 같은 형태로 cpp 파일에 메서드 본문을 작성할 수 있습니다. 이 때, 메서드의 시그니처에 전체 네임스페이스가 지정되어야 함을 유의합니다.

windows.h 헤더 파일 내에 포함되어있는 항목들 중 시스템 정보를 추출하는 API를 이용해보기로 합니다. 이 부분은 C#이나 기타 닷넷 환경에서는 원래 Platform Invoke를 통하여 우회적으로 마샬링해야 하는 부분이지만 C++ CLR의 특성에 따라 Native Code를 평소처럼 실행할 수 있다는 것을 보여줍니다. SYSTEM_INFO 구조체의 주소값을 전달하여 시스템 정보를 구조체에 채우도록 만들고 이를 ASP.NET 서비스에서 보여준다는 것이 예제 프로그램의 컨셉입니다.

Label 컨트롤을 생성하기 위하여 gcnew 연산자를 사용하였습니다. 역시 C++에서 원래 사용하던 new 연산자와 구분되는 것입니다. gcnew 연산자로 관리되는 객체를 만들고, Text 프로퍼티에 문자열을 지정하였습니다. 관리 객체에 지정되는 문자열은 자동으로 System::String의 인스턴스로 분류되어 처리되도록 만들어져 있기 때문에 유니코드 문장임을 나타내는 접두사 L 없이도 쓰일 수 있습니다. 또한, 아랫쪽 코드를 보면 System::String 형식에만 정의되어있는 문자열간 합치기 기능이 C++에서도 동작하는 것을 볼 수 있습니다.

위의 예제 코드를 작성한 다음, 결과를 확인하기 위하여 아래와 같이 IIS 7.0에서 사용할 수 있는 web.config 파일을 작성하여 웹 어플리케이션 디렉터리를 구축하고, 해당 웹 어플리케이션 디렉터리 바로 아래의 Bin 폴더에 이 프로젝트로 빌드한 DLL을 저장하였습니다.

위의 내용에서 확인해야 할 부분이 두 가지가 있습니다. IIS 7의 system.webServer 섹션은 닷넷 프레임워크가 처리하는 것이 아니라 IIS 7이 스스로 처리하는 부분입니다. 우선 핸들러에 type이라고 되어있는 부분은 닷넷 프레임워크에서 불러들일 IHttpHandler 인터페이스와 호환되는 형식의 약식 명칭을 지정하는 부분입니다. Page 클래스를 상속함으로서 이 부분이 자동으로 구현되었기 때문에 우리가 방금 작성한 C++ CLR 클래스의 약식 명칭을 여기에 기술합니다. 네임스페이스와 클래스 이름, 그리고 Bin 폴더 내에 들어있는 클래스 라이브러리의 어셈블리 이름을 여기에 기출합니다. 그리고 preCondition에서는 이 핸들러가 통합 모드에서 실행되어야 하고 닷넷 프레임워크 2.0 런타임을 사용하여 구동되어야 함을 표기하고 있습니다.

이제 실행 결과를 살펴보도록 하겠습니다.

C++ CLR이 Native Code와 잘 연동되어 ASP.NET 서비스를 수행하고 있는 것을 볼 수 있습니다. 여기서는 공식적으로 프로젝트 템플릿이 제공된 것이 아니라서 이와 같이 간소한 형태로만 프로그램을 작성하였지만 C++ CLR로도 이와 같이 프로그램 작성을 할 수 있다는 것을 확인할 수 있었습니다. Platform Invoke로 해결하기 어려운 문제는 이와 같이 프로그램의 형태에 제한을 갖지 않고 직접 C++의 힘을 빌릴 수도 있다는 것을 기억하면 쉽게 문제를 풀어나갈 수 있을 것입니다.

참고로 C++/CLI의 ECMA 표준안 문서는 http://www.ecma-international.org/publications/standards/Ecma-372.htm 에서 확인가능합니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Exploring2009. 2. 11. 01:27

강성훈님의 개인 도메인 영역에서 흥미로운 문서를 하나 발견하였습니다. 상당한 노력이 뒷받침된 것으로 보이는 중요한 문서였는데 바로 Microsoft C++ 컴파일러의 이름 변경 체계 문서입니다.

http://mearie.org/documents/mscmangle

문서에 대한 내용은 더 구체적이고 더 정확한 방향으로 업데이트 되어 나갈 것입니다. 이러한 규칙을 일정 수준 이상 분석하여 매칭시킬 수 있다면 xPlatform이 닷넷 프레임워크가 기본적으로 제공하는 C 언어나 COM, ActiveX 같은 일상적인 언어 환경을 넘어서서 Visual C++이 사용하는 특유의 이름 변경 기술에 즉시 바인딩할 수 있는 기반 기술을 C++ 컴파일러가 아닌 곳에서 구현할 수 있을지도 모르겠다는 생각이 듭니다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Windows + .NET2007. 10. 25. 01:28
우연히 printf 계열의 함수들에 대한 플랫폼 호출 방법에 대한 자료를 찾는 도중 재미있는 글을 발견하였습니다. C#의 공식 사양에 포함되지 않은 Microsoft C# 컴파일러의 특수한 기능들 (Mono나 DotGNU의 C# 컴파일러에는 존재하지 않거나 의도하지 않은 예외가 발생할 수도 있습니다.)을 알게 되었습니다.

주의: 비공식 키워드를 사용하는 것에 대한 책임은 프로그래머에게 달려있습니다. 다른 언어들과의 호환성 문제와 부딪히지 않으려면 이러한 비공식 키워드의 사용에 주의해야만 합니다.

TypedReference에 대한 비공식 키워드

TypedReference 형식은 관리되는 객체에 대한 명확한 주소 정보 및 핸들 정보를 가리키는 특수한 객체입니다. TypedReference 형식의 객체를 만들기 위한 비공식 키워드가 C#에 존재합니다.

__makeref(변수) : 괄호 안에 TypedReference 형식으로 조사하기를 원하는 객체를 지정하면 되는데, 여기에는 값 형식의 변수가 올 수도 있습니다. 예를 들면 다음과 같습니다.

int x = 0;
TypedReference xt = __makeref(x);

__reftype(TypedReference 객체) : 괄호 안에 TypedReference 객체를 지정하면 TypedReference 객체가 원래 가리키고 있던 객체의 형식 정보를 반환합니다. 예를 들어, 위의 예에서 System.Int32에 대한 TypedReference를 만들었는데 이 키워드를 사용함으로서 System.Int32에 대한 Type 객체가 반환됩니다.

int x = 0;
TypedReference xt = __makeref(x);
Type xt2 = __reftype(xt);

__refvalue(TypedReference 객체, 가져오기 원하는 형식) : 괄호 안에 TypedReference 객체를 첫 인수로 지정하고, TypedReference가 가리키고 있는 실제 객체에 대한 형식명을 두 번째 인수로 지정합니다. 이 키워드를 이용하여 TypedReference 객체로부터 곧바로 원래의 객체를 가져올 수 있습니다.

int x = 0;
TypedReference xt = __makeref(x);
Type xt2 = __reftype(xt);
int y = __refvalue(xt, int);

printf, sprintf, fprintf와 같이 C 언어에서만 사용하는 가변 인수를 C#에서도 도입하기

va_args, va_start, va_end와 같은 매크로 함수를 혹시 기억하십니까? printf 같이 인수를 가변적으로 조절할 수 있는 함수를 디자인하기 위하여 사용했던 함수들입니다. 이러한 함수들을 흉내내기 위하여 C#에서는 params 키워드를 제공하였고 그 결과 가변 인수처럼 동작하면서도 결과적으로 1차원 배열을 다룰 수 있는 향상된 가변 인수 처리법을 제공할 수 있게 되었습니다. 하지만 이렇게 변경된 가변 인수 처리법은 종전의 C 언어 스타일과는 크게 다르기 때문에 C 언어를 위하여 디자인된 printf 계의 함수들은 사용할 수 없는 것 처럼 이야기되어왔습니다. 하지만 지금 소개하는 __arglist 키워드를 이용함으로서 이런 한계를 극복할 수 있습니다.

[SecurityPermission(SecurityAction.LinkDemand)]
[DllImport(ModuleName, CharSet = CharSet.Ansi)]
protected static extern int _cprintf(string fmt, __arglist);

__arglist라는 키워드를 주목합니다. 매개 변수 형식 선언이 아님에도 불구하고 사용할 수 있다는 것이 매우 특이한데, 바로 이것이 C 언어 스타일의 가변 인수여야 함을 컴파일러에게 알려주는 힌트가 됩니다. 하지만 이렇게 선언하면 뒷쪽에 가변 인수를 제공하기 위하여 __arglist() 키워드를 사용하여야 하지만, __arglist라는 키워드를 지원하지 못하는 다른 프로그래밍 언어에서는 사용할 수 없습니다.

이제 위의 _cprintf 함수를 부르는 예제를 보기로 합니다.

int result = _cprintf("%d", __arglist(30));

그렇습니다. __arglist라는 가상의 매크로에 필요한 만큼 인수를 던져주면 됩니다. 그러면, 여기서 궁금한 점이 하나 더 생기는데 __arglist를 params 키워드 대신해서 사용할 수도 있을까에 대한 의문입니다. 그 답은 "Yes"입니다. 다음의 코드를 보겠습니다.

protected void Page_Load(Object sender, EventArgs e)
{
   int x=85;
   string y = "a stringy thingy";
   double d=19.45;
   WriteToPage(__arglist(x,y,d));
}

public  void WriteToPage(__arglist)
{
   ArgIterator ai = new ArgIterator(__arglist);
   while(ai.GetRemainingCount() >0)
   {
      TypedReference tr = ai.GetNextArg();
      Response.Write(TypedReference.ToObject(tr)+"<BR>");
   }
}

int, string, double 형의 변수를 선언하고 __arglist(x,y,d)로 이들 인수를 던집니다. 그러면 WriteToPage 메서드에서는 이렇게 받아들인 인수들을 조회하기 위하여 ArgIterator 객체를 사용하여 하나씩 조회합니다. ArgIterator 객체로 조회한 매개 변수들은 TypedReference로 포장된 객체들이므로 실제 객체를 위의 코드처럼 TypedReference.ToObject 메서드로 가져오거나 __refvalue 키워드를 이용하여 가져와서 사용하는 것입니다.

자료 출처: http://www.eggheadcafe.com/articles/20030114.asp
Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

  1. 댓글 남겨주신 것 보고 따라 들어왔더니 이런 좋은 정보가!
    마치 VB에서 ObjPtr에 대해 알게 된 것 같은 기분이 들어요 :)

    2007.11.20 01:20 [ ADDR : EDIT/ DEL : REPLY ]

Windows + .NET2007. 2. 25. 15:01

C와 C++에서 사용하는 버클리 소켓은 데이터를 주거나 받을 때 char 형식의 배열을 이용한다. .NET Framework에서도 char 형식과 가장 근접한 데이터 형식인 byte 형식의 배열을 이용한다. 하지만 약간의 호기심이 생겼다. 생각없이 사용하는 이들 소켓 API의 두 데이터 타입은 과연 숫자 범위까지 같은것일까?

C와 C++의 char 데이터 형식은 -128 ~ +127까지를 표현할 수 있다. 반면 .NET Framework의 byte는 0 ~ +255까지 표현이 가능하다. 정작 C와 C++과 호환성을 유지하기 위해서는 byte가 아닌 sbyte여야 했는데 왜 byte를 사용하게 된 것일까? sbyte는 char와 완전히 같은 데이터 범위를 보장함과 동시에 크기도 같다. 하지만 CLSCompliant(false) 플래그가 붙어있고 sbyte를 기반으로 구현된 소켓 API는 닷넷에 없다.

그래서 간단히 실험을 해보았다.

우선 .NET Framework의 소켓에서 BSD 소켓으로 데이터를 보내보았다. 물론 두 데이터 타입이 특별한 처리를 하지 않고도 표현할 수 있는 범위의 수인 0 ~ 127까지는 특이한 점이 없었다. 하지만 128 ~ 255의 값은 BSD 소켓에서 어떻게 받아들여질까? 대강 예상하고 있었고 실제로도 그렇게 되었는데, 음수로 뒤집어서 전달되었다. 순환 오버플로우와 유사하다는 생각이 들었다.

이번엔 반대로 BSD 소켓에서 .NET Framework의 소켓으로 데이터를 보내보았다. 위와 마찬가지로 0 ~ 127까지는 있는 그대로 전달되었다. 하지만 -128 ~ -1까지의 값은 음수로 전송되었지만 .NET Framework의 입장에서는 127 이후부터 255 사이의 양수값으로 바뀌어 들어갔다. 이 역시 순환 오버플로우와 유사한 동작이었다.

영양가 없는 실험이었지만 나름 궁금함은 풀어볼 수 있어서 좋았던것 같다. 그리고 결론을 하나 더 얻었는데, 실질적으로 우리가 네트워크를 통해서 전송하고자 하는 데이터의 범위는 0 ~ 127 안일 확률이 매우 높다. 2바이트 문자열과 유니코드 문자열도 결국은 이 범위 안에서 처리하도록 만들어지게 된다고 생각할 수 있겠다.

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

Windows + .NET2006. 12. 12. 10:20
Visual C++ Debugger는 Breakpoint를 어떻게 감지해내는 것일까? 원리는 아주 간단하다. 어셈블리어를 공부해보신 분들이라면 인터럽트라고 하는 기능을 들어본 적이 있을 것이다. Breakpoint를 지정한 부분에 인터럽트 코드를 삽입하여 컴파일하는 것이다. 그렇다면 우리가 직접 Breakpoint를 코딩으로 구현하는 것도 가능하지 않을까? 가능하다!

__asm
{
   int 3
}

위와 같은 코드를 실행해보면 Visual C++ Debugger가 정확히 해당 위치에서 멈추는 것을 볼 수 있다. 그러면 위와 같은 코드 대신 좀 더 직관적인 코드를 만드는법은 없을까? 매크로 구문을 이용하면 된다. 단, 이와 같은 구문은 디버그 모드에 한정하여 쓰는 것이 좋겠다.

#define BREAKPOINT __asm \
{ \
   int 3 \
} \

inline void SetBreakPoint(void)
{
   #ifdef DEBUG
       BREAKPOINT
   #endif
}

위와 같이 코드를 작성하고 따로 헤더 파일로 분리해 놓은 다음 SetBreakPoint 함수만 원하는 곳에 걸어두기만 하면 된다. SetBreakPoint 안에서 걸리는게 아니냐고 묻는다면 걱정하지 않아도 된다. 왜냐면 inline 함수이기때문이다. 익히 알다시피 inline 함수는 Call Stack에 영향을 주지 않는 함수이다.

그리고 SetBreakPoint 함수를 릴리즈 모드에서 사용할 경우 아무것도 실행하지 않게된다. 그러므로 #ifdef ~ #endif 전처리기 구문을 굳이 써놓지 않더라도 무방하다.

출처: http://www.debuglab.com/knowledge/int3.html
Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

  1. 오옹.. 재미있네. 이 기능을 쓰면 굳이 복잡한 VC 디버거 안배우고 조건에 따른 BP나 재미있는 응용이 가능할듯 ㅎㅎ

    2006.12.12 14:24 [ ADDR : EDIT/ DEL : REPLY ]

Visual C++2006. 12. 4. 21:58

1. IDispatch 인터페이스에 대한 COM Smart Pointer 만드는 법

[CODE]
_com_ptr_t<_com_IIID<IDispatch, &__uuidof(IDispatch)> > oDispatch1(/* 이곳에 Interface Pointer를 인수로 지정한다. */);
[/CODE]

2. 이것을 매크로 구문으로 만든다면...

[CODE]
#ifndef COM_PTR
#define COM_PTR(x) _com_ptr_t<_com_IIID<x, &__uuidof(x)> >
#endif // COM_PTR

COM_PTR(IDispatch) oDispatch1(/* 이곳에 Interface Pointer를 인수로 지정한다. */);
[/CODE]

* 필요한 헤더 파일: comip.h

Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요

포트폴리오2005. 1. 9. 09:28

오랫만입니다. ^^; 그 동안 잘 지내셨는지요. 간단한 프로그램을 하나 올리고 갑니다. 요 근래 들어서 바쁜일이 굉장히 많군요. 이 프로그램은 C/C++ 헤더 파일의 #define 정의문을 검색하는 유틸리티입니다. xpInterop 프로젝트에서 자주 사용될 유틸리티이기도 합니다. 많은 활용 바랍니다. ^^

using System;
using System.IO;
using System.Collections;

namespace DevDream.Debug.ConstantCollector
{
public sealed class MainObject
{
public static ArrayList GetMultipleHeaderList(string directoryPath, bool writeOutConsole)
{
  DirectoryInfo di = new DirectoryInfo(@directoryPath);

  if(!di.Exists)
   throw new DirectoryNotFoundException(@directoryPath.Trim());

  FileInfo[] fiCollection = di.GetFiles("*.h*");
  ArrayList universalResults = new ArrayList();

  foreach(FileInfo fi in fiCollection)
  {
   if(writeOutConsole)
    Console.WriteLine(fi.Name + " Results: ");

  foreach(string element in GetHeaderList(fi.FullName, writeOutConsole))
    universalResults.Add(element);
  }

 if(writeOutConsole)
   Console.WriteLine("Total Count: " + universalResults.Count.ToString());

  return universalResults;
}

public static ArrayList GetHeaderList(string filePath, bool writeOutConsole)
{
  StreamReader sr = new StreamReader(@filePath.Trim(), true);
  string buffer = sr.ReadToEnd().Trim();
  sr.Close();

  ArrayList parseUnit = new ArrayList(buffer.Split('\r', '\n'));
  ArrayList realParseUnit = new ArrayList();
  string multilineBuffer = String.Empty;
  bool multiline = false;

 foreach(string element in parseUnit)
  {
   if(element.Trim().Length > 0 && element.Trim().StartsWith("#define"))
   {
    multiline = element.Trim().EndsWith("\\");

   if(multiline || multilineBuffer.Trim().Length > 0)
    {
     multilineBuffer += element.Trim().Replace("#define", String.Empty).TrimEnd('\\').Trim();

    if(!multiline)
     {
      realParseUnit.Add(multilineBuffer.Trim());
      multilineBuffer = String.Empty;
     }
    }
    else if(multilineBuffer.Trim().Length <= 0)
     realParseUnit.Add(element.Trim().Replace("#define ", String.Empty));
   }
  }

  if(writeOutConsole)
  {
   foreach(string realElement in realParseUnit)
    Console.Out.WriteLine("\t" + realElement);

 Console.Out.WriteLine();
  }

  return realParseUnit;
}

[MTAThread()]
public static void Main(string[] arguments)
{
  try
  {
   if(arguments.LongLength <= 0)
   {
    Console.WriteLine("Error: Please specify target file path or directory path.\n");
    Environment.Exit(-1);
   }

  if(arguments.LongLength > 1)
    Console.WriteLine("Warning: This program does not process multiple parameters.\n");

  if(new DirectoryInfo(@arguments[0].Trim()).Exists)
    GetMultipleHeaderList(@arguments[0].Trim(), true);
   else if(new FileInfo(@arguments[0].Trim()).Exists)
    GetHeaderList(@arguments[0].Trim(), true);
   else
   {
    Console.WriteLine("Error: Selected path is invalid path.");
    Environment.Exit(-1);
   }

  Environment.Exit(0);
  }
  catch
  {
   Console.WriteLine("Error: Unhandled Exception Throwed.");
   Environment.Exit(-1);
  }
}
}
}
Posted by Cloud Developer 남정현 (rkttu.com)

댓글을 달아 주세요