전글에서 XCode상에서 C++모듈을 사용하는 방법을 알아보았다.

이번엔 단순이 wrapper클래스를 만들어 C++모듈을 의식하지 않고 Objective-C에서 사용할 수 있도록 wrapper메소드를 만들어보자.


아래와 같은  C++ 클래스 라이브러리가 있다고 치자.

Wrapped.hpp

#ifndef __WRAPPED_H__

#define __WRAPPED_H__


class CWrapped

{

public:

 CWrapped(int param1, int param2);

 unsigned int doSomething();

}


#endif

Wrapped.cpp

#include "Wrapped.hpp"


CWrapped::CWrapped(int param1, int param2)

{

 // do something

}


unsigned int CWrapped::doSomething()

{

 // do something

 return 0;

}


이것을Objective-C++의 문법으로 wrap해야 하지만 이 wrap를 Objective-C에서 이용하기 위해서는 조금 해더파일의 C++의 문법을 사용하지 않는 단순한 Objective-C 문법으로 하지 않으면 안된다.

특히 class키워드를 사용하지 않기위해 Objective-C++ 의 헤더파일은 #ifdef 을 사용한다.


Wrapper.h (헤더파일)

#import <Foundation/NSObject.h>


// declare CWrapped class for .mm (Obj-C++) files

#ifdef __cplusplus

class CWrapped;

#endif

// declare CWrapped class for .m (Obj-C) files (do not use the "class" keyword.)

#ifdef __OBJC__

#ifndef __cplusplus

typedef void CWrapped;

#endif

#endif


@interface Wrapper : NSObject {

 CWrapped* mWrapped;

}

- (id)init:(int)param param2:(int)param2;

- (unsigned int)doSomething;

@end


Wrapper.mm (구현부분)

#import "Wrapper.h"


@implementation Wrapper


- (id)init:(int)param1 param2:(int)param2

{

 if (self = [super init]) {

  mWrapped = new CWrapped(param1, param2);

 }

 return self;

}


- (void)dealloc

{

 delete mWrapped;

 [super dealloc];

}


- (unsigned int)doSomething

{

 return mWrapped->doSomething();

}


@end


Objective-C에서는 아래와 같이 이용할 수 있다.


main.m

#import "Wrapper.h" // Objective-C 에서 보는 class CWrapped 가 아닌 typedef void CWrapped 이기때문에 컴파일이 됨.


int main(int argc, char **argv)

{

 Wrapper *wrapper = [[Wrapper alloc] init:10 param2:10];

 unsigned int result = [wrapper doSomething];

 [wrapper dealloc];

}


위의 코드는 실제로 돌려보지는 않았다. 아래는 참고사이트

http://note.sonots.com/Comp/CompLang/Cocoa/ObjectiveCWrapper.html


이 코드를 베이스로 Wrapper클래스를 만들기 했는데 귀찮아서 올리기는 그렇고..

위의 코드를 참고로 기본틀을 만들고 필요한 것은 적당히 스택플로우를 참고하면 원하는 Wrapper클래스를 만들 수 있을것이다.


나의 경우는 unsigned char*를 NSData로 형변환해야 하는등에 귀찮은 작업이 있었지만 스택플로우의 힘으로 모두 클리어.

생각대로 잘 동작한다.


끝.

Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요

XCode로 로 개발중에 C++로 개발된 모듈을 추가해야 할 일이 생겼다.

어차피 Objective-C도 C언어에서부터 나온거라 그냥 추가해주면 될줄 알았지만 당연하게도XCode는  에러를 뱉어내면서 저항을 했다.

나중에 이런작업을 또 할까... 없을거라 생각되지만 혹시나 해서 잊어버리기전에 블로그에 적어놓자.

인터넷을 찾아본 결과 몇가지 설정이 필요하고 XCode에 필요한 규칙이 있었다.


먼저 샘플 cpp 파일을 만들어보자. 파일추가에서 아래와같이 선택하면 간단히 템플릿이 만들어진다.



추가된 파일에 cpp형식으로 샘플코드를 넣어보자.


Sample.h 와 Sample.cpp파일            

 


자..이제 실제로 뷰 콘트롤러에서 불러보자.

참고로 cpp파일을 이용하기 위해서는 ViewController.mm와 같이 확장자를 mm 으로 변경 해 주어야 한다.



Hello 함수가 정상적으로 잘 호출되었다.



그러나.. 실제 프로젝트에 적용하니 또다시 XCode에서 반항하며 알수없는 에러들을 내뱉었다.

인터넷으로 여기저기 알아본 결과 스택플로우에서 해결방법 발견!

http://stackoverflow.com/questions/6913637/xcode-4-2-c0x-libc-cannot-find-iostream


읽어보니 이유는 모르겠지만 설정을 두군데 정도 손으 봐야 한다.

Build Settings에서 C++ Standrad Library 를 libstdc++로 변경 그리고 Compile Sources As 를 Objective-C++로 바꿔준다.



어쨋든 성공은 했으니 좋다.



Posted by 악당잰 트랙백 0 : 댓글 2

댓글을 달아 주세요

  1. addr | edit/del | reply BlogIcon 곱게자란녀석 2015.01.11 17:16 신고

    안녕하세요. 같은 문제에 봉착하였는데.. 전 해결이 안되서.. 여쭤보려고 문의드렸습니다.
    전 c 파일과 cpp 파일을 전부 사용해야 하는 경우인데요.. Apple Mach 0 linker error 를 자꾸 내뱉습니다.
    cpp로 작성된 함수명들에 대해 에러를 내뿜고 있구요.
    댓글엔 그림을 넣을 수 없어 제가 다른곳에 질문글 올렸던 링크도 같이 드립니다...
    http://www.clien.net/cs2/bbs/board.php?bo_table=cm_app&wr_id=12324

    • addr | edit/del BlogIcon 악당잰 2015.01.11 19:07 신고

      도움이 될지는 모르겠으나 제가 아는 한도내에서 답변을 드리자면..

      C, C++로 만들어진 정적 라이브러리를 이용하시나요?
      그렇다면 arm64를 적용하지 않은채 빌드된 라이브러리에선 캡쳐와 같은 에러가 발생한 경험이 있습니다.
      라이브러리를 arm64용으로 빌드해서 달라고 하면 됩니다.

      c, cpp 파일을 직접 프로젝트에 넣어서 사용하신다면 캡쳐에러만 가지고는 알수가 없네요.
      다만, objective-c 에서는 기본적으로 c++은 그냥그대로 사용 못하는걸루 알고 있구요. c의 경우도 구조체 같은 경우 ARC를 먹지 않기 때문에
      결국은 오브젝티브C용으로 랩핑을 해줘야 합니다.

      도움이 되었는지 모르겠네요..

지금 참가하고 있는 프로젝트가 위의 세개(구글드라이브, 스카이드라이브, 드롭박스)의 크라우드 드라이브를 연동하는 기능이 있는 앱이다.

덕분에 이 세개의 API를 한번에 경험할 수 있는 원치않는 기회가 생겼다.





기술적인 부분은 절대적으로 블로그의 글보다는 디벨롭페이지를 적극추천한다.

이유는 이들 API의 업데이트도 빠를 뿐더러 iOS도 주기적으로 업그레이드가 되면서 블로그에 있는 정보는 예전정보일 경우가 많기 때문이다.

예를들어 deprecated된 메소드도 있다던지 더 간단하게 구현하는 메소드가 생겼다던지 하는..


기본적으로 각 서비스 디벨로퍼 튜토리얼 페이지를 참고하여 기본골격을 만든다음 구체적인 처리에 대한 궁금함은 기술자 블로그나 스택플로우를 검색하는 식으로 하는것이 가장 효율적이라고 생각한다.


드롭박스 디벨로퍼 페이지

https://www.dropbox.com/developers


스카이드라이브 디벨로퍼 페이지

http://msdn.microsoft.com/en-US/live


구글드라이브 디벨로퍼 페이지

https://developers.google.com/drive/


개인적으로는 드롭박스API가 가장 직관적이고 쓰기 편했는데 그 이유는 폴더나 파일을 열거나 폴더일람을 보여주거나 할경우 Path라는 직관적인 키를 사용했기 때문이다.

한편, SkyDrive나 Google 드라이브의 경우는 각각 ObjectId, FolderId 등으로 파일, 폴더를 다루는 방식이었는데 조금 생소할 뿐이지 원리는 비슷하다.


기능면에서는 구글 드라이브가 가장 많은듯 했고 ..(그만큼 더 복잡했음) 드롭박스는 심플한 느낌에 있을건 대부분 있는 느낌.(iOS 를 개발하는 사람이라면 익숙한 방식) 스카이 드라이브는 뭐 그냥 그렇다. 

이글은 iOS기준에서 설명한 글이기 때문에 다른 운영체제에서는 다소 느낌이 다를 수도 있다.


기술적인 내용은 개발해 나아가면서 추가할 생각이다.




Posted by 악당잰 트랙백 0 : 댓글 3

댓글을 달아 주세요

  1. addr | edit/del | reply 행인 2013.07.24 13:15

    저도 이번에 api연동을 해야하는 프로젝트의 일원이 되었는데요 ^_ㅠ
    많이 어렵나요??

    • addr | edit/del BlogIcon 악당잰 2013.07.30 22:58 신고

      프로그래밍 경험이 있으시면 어렵진 않구요. 이용할 서비스 API개발자페이지만 잘 이용하한다면 잘 될거라 생각합니다.

  2. addr | edit/del | reply 2014.02.10 09:20

    비밀댓글입니다

자초지종을 얘기하자면 회사 현장에서 예전사람이 작업을 했던 iPhone소스를 압축 파일로 넘겨받았다.

이런식으로 소스를 준 이유야 물론 소스관리서버(SVN 또는 Git)를 이용하질 않았기 때문일거다.

뭐 환경이 그러니 로컬에서 수정하는 식의 작업을 하게 됬는데...

워낙 사양의 변경이 잦아 다시 뒤로 돌리는 일이 많아지고 그래서 로컬에서만이라도 소스이력을 관리해야할 필요가 생겼다.


다행히도 XCode에는 로컬Git를 이용할수 있으므로 그걸 사용하려고 했지만.., 이런식으로..



 

이메뉴는 프로젝트 처음 실행시에만 나오므로 나의경우는 이미 프로젝트가 생성된것이니 메뉴에서는 불가능..


인터넷을 좀 검색했지만 좀처럼 답을 찾을수 없었는데 다시생각해보니 Git를 사용해본 사람이라면 간단히 해결될 문제였다.

메뉴에서 선택하여 Git를 만들지 못하니 그냥 커맨드로 하면 되는거다.


1. 터미널을 열고 소스폴더로 이동한다.

2. git init 명령을 실행하여 Git생성

3. git add . 을 실행하여 폴더에 모든 파일을 추가(옆에 점을 꼭 찍어야함)

4. git commit -a -m "init commit" 을 실행하여 커밋

5. XCode를 실행하여 프로젝트를 열면 Git을 사용할수 있다. 오거나이져에도 자동으로 보임.


결국 Git에 대한 나의 무지로 삽질을 좀 했는데 Git랑 조금이나마 가까워진것에 의미를 두자.



Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요

지금 하는 프로젝트 어플에서 특정영역을 터치하면 처리해야 되는 부분이 있다.


처음에는 버튼으로 간단히 해결하려고 했지만... 세상에 쉬운건 없었다.

 그 특정영역이 사각형이 아니라 삼각형. 혹은 다각형 도형이 될수도 있는 상태.

억지로 버튼으로 할 경우 일부분은 터치가 인식할 수 없기 때문에... 뭐 당연하 얘기지만..



그러다면... 무식한 방법이지만 버튼을 오밀조밀 여러개를 배치하여 해결을 할까? 라는 꼼수도 생각해 봤지만 최후에 정말 안될경우에 그렇게 하기로 하고 머리를 굴리기 시작했다.


구글로 검색한 결과  Cocos2d를 이용하는 방법들이 여기저기 소개되어 있긴한데 . 아.. 그런데 이거 하나때문에 그 큰 라이브러리를 써야돼? 라는 조금 거부감이 느껴져 망설이던 차 맥 개발카페에서 어떤분이 해결가능한 메서드를 알려주셨다.


CGPathContainsPoint

Checks whether a point is contained in a graphics path.

bool CGPathContainsPoint (
   CGPathRef path,
   const CGAffineTransform *m,
   CGPoint point,
   bool eoFill
);
터치를 인식하고 싶은 영역을 패스로 연결한 후 이 메소드를 이용하여 판정하면 된다.

물론 Path가 아닌 Rect도 있었다.

CGRectContainsPoint

Returns whether a rectangle contains a specified point.

bool CGRectContainsPoint (
   CGRect rect,
   CGPoint point
);

위에 메소드를 이용해 테스트를 해 보았다.


- (void)viewDidLoad

{

    [super viewDidLoad];

    _cellPath = [self cellPath];    //패스생성

    BOOL b = [self containsPoint:CGPointMake(80, 50)];  //판정

    NSLog(@"%d",b);

}


- (CGPathRef) cellPath

{

    if( ! _cellPath ) {

        CGPoint p[3] = { {0,0}, {100,10}, {100,110}};

        CGMutablePathRef path = CGPathCreateMutable();

        CGPathAddLines(path, NULL, p, 3);

        CGPathCloseSubpath(path);

        _cellPath = path;

    }

    return _cellPath;

}


- (BOOL)containsPoint:(CGPoint)p

{

    return [super containsPoint: p] && CGPathContainsPoint( _cellPath, NULL, p, NO );

}



무사히 잘 되는걸 확인했다. 이젠 소스를 뜯어고치는 일만 남았구나..


Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요

테스트 데이터를 읽어들여 기본값을 셋팅하거나 할때 csv형식의 파일을 사용하게 된다.

그렇지만 윈도우나 맥의경우 각각 캐리지리턴(개행문자)가 다르므로 개행을 구분할 필요가 있는데 한번에 간단히 처리되는 방법이 있다.


XCode상에 프로퍼티에서 파일형식을 확인할 수 있다.




소스는 다음과 같다.


    // 1.ラインフィードバックで行を区別する。

    NSScanner *scanner = [NSScanner scannerWithString:text];

    

    // 改行文字の集合を取得

    NSCharacterSet *chSet = [NSCharacterSet newlineCharacterSet];

    // 一行ずつの読み込み

    NSString *line = nil;

    

    while(![scanner isAtEnd]) {

        // 一行読み込み

        [scanner scanUpToCharactersFromSet:chSet intoString:&line];

        NSLog(@"line = %@", line);

        // カンマ「,」で区切る。

        NSArray *subTmp = [line componentsSeparatedByString:@","];

        

        //TODO:

        NSString *tmp1 = [NSString stringWithString:[subTmp objectAtIndex:0]];

        NSString *tmp2 = [NSString stringWithString:[subTmp objectAtIndex:1]];

        NSString *tmp3 = [NSString stringWithString:[subTmp objectAtIndex:2]];

        

        // 改行文字をスキップする。

        [scanner scanCharactersFromSet:chSet intoString:NULL];

    }


Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요

앱을 개발하다 보면 프로토타입을 만들기 위해 종이에 직접 스케치 하거나  키노트, 파워포인트를 이용한다.


실제로 개발하다보면 아이폰 화면이 생각보다 작기때문에 실제 아이폰 화면에서 레이아웃을 확인하지 않으면머리속의 이미지와는 다른결과가 나오기도 한다.



일본블로그에서 키노트로 간단히 프로토타입을 만는 방법이 있었다.

http://design.kayac.com/topics/2011/01/iphone-prototype.php


일본어로 되어 있어도 대충 알수 있는 내용이지만 몇 분간 직접 따라해 만든 것을 간단히 

번역과 설명을 추가한다.


작업순서

01. 슬라이드를 작성 (키노트)

02. PDF로 내보내기

03. 아이폰으로 전송 (내 경우 드롭박스DropBox에 보냄)

04. 앱실행 (PDF열기)



01. 슬라이드 작성시 슬라이드 크기 320x480으로 설정한다.





02. 각각 만들어 놓은 컨트롤의 하이퍼링크로 활성화 를 체크하고 화면 이동할 슬라이드를 설정해 준다.




03. 작성이 끝나면 보내기를 선택. PDF로 출력한다.





04.만들어진 PDF를 드롭박스에 올려 아이폰로 실행시킨 후 확인.


Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요

구글분석기를 앱에적용해 보자.

일반적으로 웹사이트나 블로그에 액서스정보(통계)를 얻기 위해서 구글 분석기를 많이 사용합니다만 

앱에서도 그걸 원하는 고객들이 있더군요. 그래서 조사해 보니 안드로이드나 iOS와 같은 네이티브 앱에서도 

사용할 수 있게 구글에서 제공해주는 SDK가 있다는것을 알았습니다.


  • 아래 링크참고.

https://developers.google.com/analytics/devguides/collection/ios/devguide?hl=ko-KR#overview

일단은 iOS용 SDK를 다운로드 한 후에 EasyTracker라는 라이브러리를 다운로드 합니다. 

이름에서도 포스가 느껴지듯이 쉽게 트랙킹을 하기위한 라이브러리인듯 하군요. 

예상외로 몇가지의 간단한 설정으로 구글분석기가 적용되었습니다.


사전에 필요한작업
당연히 구글 아날리틱스(분석기)가입 필요
AccountId취득. 구글ID가 아닙니다.

EsayTracker Library설정
EasyTracker.plist 에 있는 accountId에 취득한 아이디를 설정
EasyTracker.plist 에 있는 FirstViewController 와 First View 라고 되어있는 항목은 맵핑정보같음. 분석하고 싶은 뷰 콘트롤러정보를 입력해준다. (만약 설정하지 않으면 컨트롤러명이 그대로 분석기로 전송 되는것 같음)

추가 설정정보
plist에 저장하는 맵핑된 뷰명에는 앞에 「/」를 붙여줘야 하는것 같음.
라이브러리 추가시 프레임워크추가 메뉴에서 추가. 2개의모듈 libGoogleAnalytics.a, libGoogleAnalytics_NoThumb.a 모두 추가해야한다.

분석기 확인
아마도 반영되는 시간이 꽤 걸리는듯.  인터넷 검색해보니 하루이틀 걸린다는데 내일이나 확인이 가능할듯.
한번 반영이 시작되면 다음부터는 하루씩은 안걸림.

잡담
EasyTracker는 UIViewController 에서 상속받아 구현되게끔 되어있어서 상속을 받아 구현하면 자동적으로 viewWillAppear이벤트에서 자동으로 구글에 정보를 보내게 됨.

지금 하고 있는 프로젝트의 경우는 UIViewController에서 이미 릴리스된 앱에 대한 것이었기 때문에 
상속받아 만들기에는 너무 영향범위가 커서 카테고리로 라이브러리를 확장하는 방식으로 고쳐서 적용하였습니다.

성공 인증샷... 




Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요

프로파티의 목록을 취득하려고 하려면 어떻게 해야할까?




출처: http://stackoverflow.com/questions/780897/how-do-i-find-all-the-property-keys-of-a-kvc-compliant-objective-c-object


프로파티 말고도 메소드이름이라던가 취득가능한것 같음. 

https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html



Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요