1. [New File] 메뉴를 이용하여 나오는 창에서 C++ 항목을 선택하세요
    - Cocoa Thouch 에서는 C++ 생성 항목이 없습니다, 아래쪽 Cocoa 항목에서 선택할 수 있습니다.

2. 파일이름을 입력하세요( CppObject.mm)
   - 헤더파일과 함께 프로젝트에 생성됩니다.

3. 클래스를 구현하세요.

 CppObject.h

    class CppObject
    {
           int  m_nMeber;
public:        
       CppObject();
       ~CppObject();
    }

 

 CppObject.mm

   CppObject::CppObject()
   {
       m_nMember = 10;
   }   
   CppObject::~CppObject()
   {
   }

4. 컴파일을 우선 해봅니다.
5. 컴파일 성공해서 빌드까지 무사히 성공되는 것을 볼 수 있습니다.

--------------------------------------
 이제 Object-C에서 직접 사용해 보시다.
--------------------------------------

1. AppDelegate 클래스의 초기화 함수에서 호출해 봅니다. 

 AppDelegate.m

 #include "CppObject.h"
 - (void) somefunction
{
   CppObject* pObj = new CppObject();
  delete pObj;
}

2. 컴파일 합니다.
3. 에러가 발생합니다.
   - Object-C는 파일확장자를 이용하여 언어를 구분하는 것 같았습니다.
   - m 확장자인 경우에는 C++ 코드를 사용할 수 없었습니다.
4. 그래서 AppDelegate.m의 확장자를 mm으로 변경합니다

 AppDelegate.mm

 #include "CppObject.h"
- (void) somefunction
{
   CppObject* pObj = new CppObject();
  delete pObj;
}

5. 다시 빌드합니다
6. 빌드 성공해서 디버깅해봅니다.
   m_pObj->m_nMember 값이 생성자에서 설정한 '10'을 가지고 있음을 알 수 있습니다.
이제부터는 C++를 자유롭게 이용할 수 있다니, 한결 개발이 자유로울 것 같네요. 

----------------------------------------------
Cocoa 객체 사용하기
----------------------------------------------

다음으로, C++ 클래스에서 Cocoa 객체를 사용할 수 있는지 테스트 해보았습니다. 
1. 아래와 같이 Cocoa 객체를 선언하고, 생성합니다. 

 CppObject.h

    class CppObject
   {
       int  m_nMeber;
       NSString*   strTitle;
public:        
       CppObject();
       ~CppObject();
    }

 

 CppObject.mm

   CppObject::CppObject()
   {
       m_nMember = 10;
       strTitle = [NSString stringWithString:@"Hello World"];
   }   

   CppObject::~CppObject()
   {
       [strTitle release];
   } 

2. 빌드 합니다.
3. 위의 테스트 코드에서 breakpoint를 설정하고 값을 확인 또는 생성자에서 값을 확인합니다.
   - strTitle이 "Hello World"를 가지고 있는 것을 볼 수 있습니다. 
이상입니다. 

결론은  C++를 사용하고 싶으면 확장자를 mm으로 사용하는 것 이었습니다. 참 쉽죠~

기존에 가지고 있던 C++ 코드가 있다면, 많은 부분을 재사용할 수 있을것 같네요.
C++를 사용함으로써 iPhone에서 다른 문제가 있는지는 저두 입문한지 얼마안되서 잘 모르겠습니다.
이부분은 저두 사용해 보면서, 추가적인 정보가 있으면 올리도록 하겠습니다.

[출처]맥부기 개발자 모임: 아이펠스님 게시물

Tag // C++, 아이폰
일단은 간단하게 기록 해 둡니다. VMWare를 이용합니다.

[기본설정]
1. VMWare leopard 10.5.7 torrent 검색(google) - 최신 XCode가 10.5.6 이상을 요구
   - iDeneb Max OSX 10.5.7 이 검색됨
2. torrent를 이용, 파일을 다운로드 하고, 압축 해제.(약 10G)
3. VMWare 6.5실행, Open메뉴에서 압축 푼 폴더에서 파일 선택
4. VMWare에서 새로운 탭이 생성되는 것을 확인
5. [Resume this virtual machine]을 선택하고 실행(기본 상태가 suspend)

※ 주의사항
- 기본상태가 suspend상태임. power-off하고 부팅하면 정상부팅 안됨
- OSX 내부에서 Shutdown 이나 Log-off 하면 안됨.
> 종료시에도 반드시 suspend 사용.

[네트웍 설정]
기본적인 네트웍이 Host 상태임
VMWare의 suspend 상태에서는 네트웍을 변경할 수 없음

1. 가상머신이 설치된 곳의 iDeneb Mac OSX 10.5.7.vmx 파일을 텍스트 에디터로 오픈
2. ethernet0.connectionType = "nat" 를 추가 (메모리 용량도 추가 가능)
3. OSX를 다시 실행(Resume)
4. 네트웍 설정에서 DHCP로 설정
5. 사파리로 웹 커넥션 테스트
6. 안되면 다시 점검

[XCode]
인터넷이 올바로 연결되었으므로
1. developer.apple.com 에서 XCode를 download & install

※ 주의사항
- OS업그레이드 하면 부팅안됨
- 종료시 반드시 suspend
- 종료 가능한 버전이 10.5.4이나, XCode가 10.5.6을 요구하므로 업그레이드 하면 부팅 안됨.

종료 가능한 정상버전 또는 방법을 알고계신 분 계시면 연락 부탁드립니다.
php/ext 또는 php/extension 내부에 php_mssql.dll 파일이 존재하는지 확인.
없으면, php 재설치 또는 해당 파일 copy 필요.
있으면, php.ini 파일에 다음 내용 기술
extension=php_mssql.dll (NT)
extension=php_mssql.so (Solaris & Linux)
혹자는 mysql_ 로 시작하는 함수들을 mssql_ 로 바꾸어야 한다고 하는데, mysql_ 로 해도 정상 작동한다.


Tag // MSSQL, php
필요한게 생겨, 네이버 영어사전 API를 이용할 일이 생겼다.
결과가 나오질 않는다. 코드를 봐도 의심가는 부분이 없고, JSON으로 했다가, DOM으로 했다가..
혹시나 하여 브라우저에 쿼리를 찍었더니, 검색 결과의 링크만 제공하고 있다.
어이없다. 문득, 사전 데이터의 저작권 때문이 아닐까 하는 생각이 들었지만,
이걸 과연 OpenAPI라 불러도 되는 걸까? 이렇게 할 거면 아예 서비스를 하지 말던가.



Tag // Naver, openapi
using System;  
using System.Data;  
using System.Data.SqlClient;  
 
public class DB_TEST  
{  
    public static void Main(string[] args)  
    {  
        SqlConnection conn = new SqlConnection();  
        conn.ConnectionString =  
            "Server=ip;database=CL_ADMIN;uid=sa;pwd=password;";  
 
       try 
       {  
          conn.Open();  
          Console.WriteLine("데이터베이스 연결성공..");  
         String log = " SELECT * FROM dbo.OB_TEST"; // 쿼리문  
          SqlCommand cmd = new SqlCommand(log, conn); // 적용  
           SqlDataReader rd = cmd.ExecuteReader(); // 쿼리 수행  
 
          while (rd.Read()) //한줄씩 잃기  
          {  
            Console.WriteLine(String.Format("{0}, {1}", rd[0],rd[1]));  
            //내용 출력하는 부분         
                 
          }  
         rd.Close();  
 
       }  
       catch 
       {  
 
            Console.WriteLine("데이터베이스 연결 실패..");  
        }  
        finally 
        {  
            if (conn != null)  
            {  
                conn.Close();  
            }  
            Console.WriteLine("데이터베이스 연결해제");  
 
        }  
    }  
}
닷넷 프레임워크 버전 변경을 했다가, 한참 고생했다.

'/xxxxx' 응용 프로그램에 서버 오류가 있습니다.

IIS 메타베이스에 액세스하지 못했습니다.

설명: 현재 웹 요청을 실행하는 동안 처리되지 않은 예외가 발생했습니다. 스택 추적을 검토하여 발생한 오류 및 코드에서 오류가 발생한 위치에 대한 자세한 정보를 확인하십시오.

예외 정보: System.Web.Hosting.HostingEnvironmentException: IIS 메타베이스에 액세스하지 못했습니다.

ASP.NET을 실행하는 데 사용되는 프로세스 계정에는 IIS 메타베이스(예: IIS://servername/W3SVC)에 대한 읽기 권한이 있어야 합니다. 메타베이스 권한을 수정하는 데 대한 자세한 내용은 http://support.microsoft.com/?kbid=267904를 참조하십시오.

소스 오류:

현재 웹 요청을 실행하는 동안 처리되지 않은 예외가 생성되었습니다. 아래의 예외 스택 추적을 사용하여 예외의 원인 및 위치 정보를 확인할 수 있습니다.

스택 추적:

[HostingEnvironmentException: IIS 메타베이스에 액세스하지 못했습니다.]
   System.Web.Configuration.MetabaseServerConfig.MapPathCaching(String siteID, VirtualPath path) +3492202
   System.Web.Configuration.MetabaseServerConfig.System.Web.Configuration.IConfigMapPath.MapPath(String siteID, VirtualPath vpath) +9
   System.Web.Hosting.HostingEnvironment.MapPathActual(VirtualPath virtualPath, Boolean permitNull) +163
   System.Web.CachedPathData.GetConfigPathData(String configPath) +382
   System.Web.CachedPathData.GetConfigPathData(String configPath) +243
   System.Web.CachedPathData.GetApplicationPathData() +68
   System.Web.CachedPathData.GetVirtualPathData(VirtualPath virtualPath, Boolean permitPathsOutsideApp) +3385711
   System.Web.Configuration.RuntimeConfig.GetLKGRuntimeConfig(VirtualPath path) +189


버전 정보: Microsoft .NET Framework 버전:2.0.50727.42; ASP.NET 버전:2.0.50727.42



해 결 방 법
aspnet_regiis.exe 도구를 사용하면 된다.
aspnet_regiis.exe 는 windows폴더에 microsoft.net 폴더 아래에 있고,
cmd에서 해당 경로를 찾아가서 아래와 같이 입력한다.
aspnet_regiis.exe -ga iwam_계정이름(컴퓨터이름)
예)C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe
그러면 iis메타베이스에 대한 접근 권한을 iwam 계정이 갖게 된다.
iwam계정은 iis 프로세스를 시작시키기 위한 식별자 계정.
그리고 나서 iis 를 열고 등록정보 중에 http 헤더부분을 보면 사용자지정 헤더부분에
X-Powered-By:APS.NET 이라고 있는지 확인 한 후,

없으면
다시 aspnet_regiis.exe를 열고
aspnet_regiis -i 
돌아가는지 확인
안되면
aspnet_regiis -e
aspnet_regiis -i
돌아가는지 확인

'지혜 이야기 > 플밍노트' 카테고리의 다른 글

NAVER OpenAPI 에 대한 잡설.  (4) 2009/02/10
C# MSSQL 접속 sample code  (0) 2008/08/31
IIS 메타베이스에 액세스 하지 못했습니다. 오류 해결  (1) 2007/10/21
C# TIP 몇가지  (0) 2007/10/04
Resource Leaking  (6) 2007/08/13
SetTimer()  (0) 2007/05/14

C#을 해 보면서 기존에 사용하던 언어와 조금 달라서 필요한 것들을 찾아 쓰고 메모해 두었던 것들을 포스팅.

키보드 이벤트 처리

특정 이벤트에서 키보드 키 메시지를 잡아야 할 때, 이벤트 처리 메소드에 전달되는 e 객체의 KeyChar속성을 이용한다. 키보드 각각의 값이 상수로 정의되어 있으므로, 원하는 키의 후킹이 가능
private void NONAME(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
 if(e.KeyChar == (int)Keys.Enter) { ... }
 또는
 if (e.KeyCode.Equals(Keys.Enter))
}

String의 Bytes단위 처리

String에는 영문자가 있을 수도 있고, 특수문자가 있을 수도 있고, 한글이 있을 수도 있다. 총 바이트 개수를 알고 싶을 때에는, 다음과 같이 한다
int length = Encoding.Default.GetByteCount(textBox1.Text);

URL로의 Redirect

LinkLabel을 붙이고, 이벤트에 보면 LinkLabel 클릭 이벤트가 존재한다. 당연히 URL로 이동을 해야 하는데 이런 부분은 속성창에서 지원해 주지 않으므로 직접 코딩한다
System.Diagnostics.Process.Start("http://dolbbi.com");

Dialog를 이용하지 않고 MessageBox의 지원 기능으로 분기하기

사용자의 요구에 따라 특정 이벤트로 분기해야 할 경우, Dialog를 생성하지 않고 MessageBox로 분기한다. 단, 복잡한 분기보다는 Yes/No의 간단한 분기에서 사용. (별거 없다 -_ -)
DialogResult result = MessageBox.Show("choose, yes or no", "messagebox", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
            switch (result)
            {
                case DialogResult.Yes:
                    // CALL EVENT
                    break;
                case DialogResult.No:
                    // CALL EVENT
                    break;
            }

'지혜 이야기 > 플밍노트' 카테고리의 다른 글

C# MSSQL 접속 sample code  (0) 2008/08/31
IIS 메타베이스에 액세스 하지 못했습니다. 오류 해결  (1) 2007/10/21
C# TIP 몇가지  (0) 2007/10/04
Resource Leaking  (6) 2007/08/13
SetTimer()  (0) 2007/05/14
DefiningSOA as an Architectural Style  (0) 2007/03/27
Tag // c#, 노트,

MFC 에서, 컨트롤의 색상을 변경하고자 할 때, OnCtlColor()을 사용한다. (버튼 컨트롤 제외)

HBRUSH CPppDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
 HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

 if( pWnd->GetDlgCtrlID() == IDC_DIC)
 {
  hbr = CreateSolidBrush( RGB(0,0,255) );
  pDC->SetBkMode( TRANSPARENT );
  pDC->SetBkColor( RGB(0,0,255) );
  pDC->SetTextColor( RGB(255,255,0) );
    
  return hbr;       
 }
 return hbr;
}


여기서 문제가 있다. 이 메소드는 해당 컨트롤을 다시 그려야 할 이유가 생길 때 마다 자동적으로 호출된다.
따라서, 프로세스의 메모리 점유가 늘어날 수 밖에 없다.
계속해서 CreateSolidBrush()를 통해 계속해서 브러시를 생성하기 때문.

프로그램 시작시, 단 한번만 브러시를 생성하고 프로그램 종료 시, 생성된 브러시를 파괴해 주는 것으로 이 부분은 해결된다. 코드는 다음과 같다.

생성자에 다음과 같은 코드를 삽입한다.
물론 hBkBrush 는 HBRUSH type 이며, 클래스 정의부분에 명시해 둔다.
hBkBrush = CreateSolidBrush(RGB(0,0,255));

그리고 위의 코드 중, 붉은색으로 된 부분을 다음과 같이 변경한다.
hbr = hBkBrush;

마지막으로, 프로그램 종료시 호출되는 파괴자나, 기타 메소드 중에 적당한 곳을 골라 브러시 객체를 파괴한다.
DeleteObject(hBkBrush);

일정 시간마다 특정한 일을 수행할 때 대개 SetTimer() 함수를 사용한다. (일정 시간이 경과할 때까지 Sleep하는 건 유치할 것같다.. ㅋㅋ) 책을 좀 찾아보니 SetTimer()는 SDK에서 제공되는 API 함수가 원조격이다. 일단, MSDN을 열어봤다.

이미지를 클릭하시면 원본크기로 보실수 있습니다.

보다시피 VC++에서 제공되는 SetTimer() 함수는 총 3개가 존재한다. 그런데, 맨 위의 CWindows::SetTimer는 ATL에서 사용되기 때문에 통상으로 사용되는 SetTimer() 함수는 SDK의 API 함수와 CWnd::SetTimer 멤버함수가 되겠다. (따라서, SetTimer()는 SDK버전과 MFC버전 두개만 정리하면 된다.)

먼저, SDK의 SetTimer() 함수의 원형을 살펴본다.

UINT SetTimer(
  HWND hWnd,    // handle of window for timer messages
  UINT nIDEvent,          // timer identifier
  UINT uElapse,           // time-out value
  TIMERPROC lpTimerFunc   // address of timer procedure
);

첫번째 인자는 SetTimer()를 호출하는 윈도우의 핸들이고, 두번째는 타이머의 ID이다. 애플리케이션은 여러 개의 독립된 타이머를 이용할 수 있다. 따라서, 각각의 타이머를 구별하기 위해 ID를 부여한다. 세번째 인자는 타이머의 주기(단위는 밀리초)이며, 마지막 인자는 타이머가 동작할 때 시스템이 호출하는 콜백함수(이를 타이머 프로시져라 한다)의 함수포인터(여기서, 타이머 프로시져의 함수이름은 자기 마음대로 결정해도 된다)이다. 즉, 일정 시간이 발생하면 해당 콜백함수를 실행하게 되는데, 거기에 우리가 필요로 하는 루틴을 넣어주면 된다.

그러면, SetTimer()에 등록하는 콜백함수(타이머 프로시져)는 어떻게 정의해야 할까? (타이머 프로시져는 콜백함수이기 때문에 함수이름은 SetTimer에 등록한 함수이름과 동일해야 하며, 시스템이 정한 호출 형식대로 정의를 해두어야 한다.)

VOID CALLBACK TimerProc(
  HWND hwnd,     // handle of window for timer messages
  UINT uMsg,     // WM_TIMER message
  UINT idEvent,  // timer identifier
  DWORD dwTime   // current system time
);

호출되는 타이머 프로시져 함수는 위와 같은 형식이다. 첫번째 인자인 hWnd는 타이머를 호출한 윈도우의 핸들이며(SetTimer()함수의 첫번째 인자를 생각할 것), 두번째는 시스템이 던져주는 타이머 메시지(항상 WM_TIMER이다), 세번째는 호출한 SetTimer함수의 Id값, 네번째는 시스템 시간이다. 위의 인자들은 TimerProc가 콜백함수이기 때문에 시스템이 알아서 던져준다. 따라서, 우리는 타이머 Id를 조사(if 내지는 switch)하여 해당 타이머에 대한 기능을 구현하면 될 것이다.

그런데, MSDN을 자세히 읽어보면 SetTimer()의 인자 중에서 콜백함수 대신 NULL을 대입하는 경우가 있다. 이 경우, 시스템은 일정 시간에 이르면 콜백함수를 호출하는 것이 아니라 애플리케이션에 WM_TIMER 메시지를 전달한다. 따라서, Win32 프로그램의 경우라면 WndProc에서 WM_TIMER 발생에 따른 처리루틴을 구현하면 된다.

정리하면, SDK의 SetTimer함수는 콜백함수에 의한 처리방식과 WM_TIMER 메시지에 대한 처리방식으로 그 사용방법이 나뉘어진다. 이는 MFC에서도 마찬가지이다. 이제 MFC의 SetTimer() 함수를 살펴보자.

UINT

CWnd::SetTimer(

            UINT nIDEvent,

            UINT nElapse,

void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT,

                                        UINT, DWORD) );

MFC의 SetTimer() 함수는 CWnd클래스의 멤버함수로 구현되어 있기 때문에 SDI, MDI, 다이얼로그 애플리케이션에서 모두 사용이 가능하다. SDK와의 차이점은 SDK의 첫번째 인자인 hWnd를 가지고 있지 않다는 점. 당연히 CWnd의 멤버함수이므로 hWnd를 알고 있기 때문일 거다. 그 점을 제외하면 SDK버전과 별반 다를게 없다.

다만, MFC에서는 타이머 프로시져를 사용하지 않을 경우 WM_TIMER의 처리를 위해서 OnTimer() 이벤트 핸들러를 추가해서 사용하면 될 것이고, 타이머 프로시져를 사용할 경우 타이머 프로시져는 전역함수이기 때문에 주윈도우(또는 주다이얼로그)의 멤버에 접근하기 위해서 다음과 같은 방법을 사용할 수 있다.

가령, 다이얼로그 기반으로 TestProg라는 애플리케이션을 작성하였을 경우

void CALLBACK TimerProc(HWND hWnd, UINT nIDEvent, UINT nElapse, DWORD dwTime)

{

    ...

    CWnd *pWnd = AfxGetMainWnd();

    CTestProgDlg *dlg = (CTestProgDlg *)pWnd;

    dlg->멤버함수();

}


이런 식으로 하면 된다.

어디선가 가져온 글인데, 다시 아무리 찾아봐도, 어디서 가져왔는지 알 수가 없다.
핵심 토큰을 기초로 하여 구글에서 검색을 해 봐도 나오지 않는다. 혹시나 원 저작자 분이 보실일이 있으면 지적해 주십사 하고, 포스팅 한다.[너무 염치없는것인가]

나온 지 꽤 되었는데도 불구하고 (요즘 세상에는 2 ~ 3개월이면 이미 과거이지 않나^^)  IBM에서 만든 멋진 자료를 발견하였다.
원문 위치 http://www-128.ibm.com/developerworks/library/ar-soastyle/index.html#author
"DefiningSOA as an Architectural Style" 이라는 제목으로서 Bris Lublinsky라는 분이 쓴 글인데 그가운데의 그림이 SOA를 풀어가가는 데 하나의 big picture이자 plan을 제공하는 것이 아닌가 싶다.

사용자 삽입 이미지
이 분이 생각하는 Enterprise SOA Concept이다. 바로 어떠한 조직의 범주 내에서 만들어 질 수 있는 Enterprise System의 범주는 SOA의 관점으로 보면 저렇게 잡히는 구나... 라는 생각이 저절로 든다.
우선 Business model이라는 기본적인 비즈니스 틀을 만든 다음 비즈니스 프로세스와 의미론적 data model로 분리해 냈다. 우리가 SOA라 하면 기본적으로 프로세스 중심 또는 인터페이스 중심의 서비스 연결로 생각하기 쉬운데 저기 그림에서 표현된 의미론적데이터 모델이라는 것은 바로 데이터 영역 또한 어플리케이션 밑에 숨어 있는 존재가 아닌 비즈니스 프로세스와 동급으로 관리된다는것이다.
저 그림 하나만으로도 해당 Layer가 명확해 지며 정답이라는 생각이 든다.
물론 어떻게 정의하고 그려나가야 할 것은 숙제이지만, 마치 콜롬부스가 달걀을 깨어 세웠듯이 기본적으로 생각만 하고 있던 것을 저렇게 그림으로 표현한 것이 아닌가.
약간 다른 이야기지만, 우리가 프로젝트를 진행할 때 프로세스, 방법론 등에 회의를 가지고 제대로 지켜지지 않는 경우를 가지고 비난하는 경우가 다분히 있다. 그러나 그러한 방법, 원칙 자체가 존재하지 않는 이상 어떻게 한 걸음 한 걸음 전진할 수 있을까.정진하는 삶에는 계획이 필요하듯이, 기본적인 틀은 반드시 필요한 법이다.