2014년 5월 16일 금요일

자바 랜덤 함수를 이용해서 간단하게 랜덤 문자열을 생성해보자.

웹통신시 간단하게 암호화 처리를 위해서, 자바에서 제공하는 랜덤 문자열 생성 함수가 있는지 잠시 찾아보니
없는것 같아(오래찾아보지 않아서 있는지 없는지 모르겠다) 고민하던 중 자바의 기본 Math.random() 함수를 약간 응용하여 간단하게 랜덤문자열을
생성 할 수 있는 클래스를 만들어보았다.
기본 힌트는 

1. 랜덤함수로 임의의 숫자를 생성하고
2. 해당 숫자를 문자열로 바꾼다음에
3. 해당 문자를 다시 base64로 인코딩 하는것이다.

아래는 유틸클래스의 전체 내용이다.
base64인코딩/디코딩 관련한 클래스는 구글 안드로이드 IAP예제에서 제공되는 Base64클래스를 가져다 사용했다. 해당 클래스 파일을 첨부해놓는다.

package com.util.crypt; 

import java.io.UnsupportedEncodingException; 

import com.util.base64.Base64; 

public class CRandomUtil { 
     
    //랜덤 양의 정수값 생성 
    public static int GetInt(int max) 
    { 
        return (int)(Math.random() * max); 
    } 
     
    //랜덤 0 ~ 1사이의 양의 실수값 생성 
    public static float GetFloat() 
    { 
        return (float)Math.random(); 
    } 
     
    //랜덤 -1 ~ 1사이의 실수값 생성 
    public static float GetUnit() 
    { 
        return ((float)Math.random() * 2.0f) - 1.0f; 
    } 
     
    //랜덤 스트링 생성 
    public static String GetString() throws UnsupportedEncodingException 
    { 
             //여기에서 생성하는 정수의 값이 클수록 긴 랜덤 문자열이 만들어진다
        int val = GetInt(500000); 
         
        String sv = String.valueOf(val); 
         
        return Base64.encode(sv.getBytes("utf-8")); 
    } 
     
    //랜덤 스트링 생성(웹전송용) 
    public static String GetStringWebSafe() throws UnsupportedEncodingException
    { 
        int val = GetInt(500000); 
         
        String sv = String.valueOf(val); 
         
        return Base64.encodeWebSafe(sv.getBytes("utf-8"), true); 
    } 
}

첨부 파일의 패키지명등을 적절하게 변경하지 않으면 오류가 날것이다.


2014년 5월 8일 목요일

포인터의 포인터, 이중 포인터에 대해서 알아보자.

 던전워즈
저번 시간에 간략하게 나마 포인터의 개념과 메모리의 구조에 대해서 알아봤다.
포인터는 어떠한 변수가 메모리 상의 어느 위치에 저장되 있는지 주소값을 갖고 있는 변수라고 했다.

그런데 포인터 중에는 특이한 포인터가 있으니 바로 이중포인터다.

일반적으로 이중 포인터는 다음과 같이 선언을 한다.

int형의 이중 포인터를 예로 들면

int **pointer;

포인터가 주소를 저장하는 변수라면 이중포인터의 역할은 무엇인가?

이중 포인터도 일반 포이터와 마찬가지로 단지 주소를 저장하는 변수일뿐이다.

그렇다면 무엇의 주소를 저장하는가가 이중포인터의 관건일 것이다.

포인터는 메모리상의 주소를 저장하고 있다.

컴퓨터에서 메모리의 주소는 결국 양의 값을 가지는 정수 값일뿐이다.

어떠한 변수값을 예로 들어보자.

int t = 120;

이라는 변수가 선언이 된다면 해당 변수는 메모리 상의 어떠한 위치에 저장이 되고 그위치에는 120이라는 값이 저장이 될것이다.

그리고 t의 포인터 를 선언해보자

int *pt = &t;

라고 선언을 하게 되면 포인터 pt는 t의 값이 저장된 주소 값을 갖게 될것이다.

만일 t가 메모리 주소 1000이라는 위치에 저장이 되었다 가정한다면 포인터 변수 pt는 1000이라는 값을 가지게 된다.

변수는 값을 메모리에 저장하고 있고 포인터 역시 변수일뿐이다.

그렇다면 pt가 가지고 있는 1000이라는 주소값또한 메모리상의 어떠한 위치에 놓여질 것이다. 이제 pt의 이중포인터를 선언해보자.

int **ppt = &pt;

pt또한 변수이기 때문에 &키워드를 사용해서 그것의 주소값을 기록할 수 있다.

ppt는 pt의 메모리 상 주소값을 가지게 된다.

즉 1000이라는 값이 메모리의 어느위치에 저장이 되있는지 ppt에 저장이 되는 것이다.

이렇게 이중포인터는 포인터의 메모리상 주소를 기록하기 위한 용도를 가지는 변수이다.

2014년 5월 6일 화요일

c++ 기본자료형과 포인터 그리고 메모리

 던전워즈
컴퓨터 프로그래밍에서 기본 자료형은 다양한 형태의 숫자들을 저장하기 위한 공간을 제공한다.
이러한 숫자 공간들은 컴퓨터의 메모리에 정해진 크기만큼의 공간을 차지하여 저장이 된다.

c또는 c++에서는 몇가지의 숫자를 저장하기 위한 기본 자료형들을 제공하는데,
컴파일러의 종류에 따라서 같은 자료형일지라도 그것이 메모리 상에서 차지하는 공간의 크기가 다르다.

VC++기준으로 기본형의 종류와 크기에 대해서 나열해 보면 다음과 같다.

---------------------------------------------------------------------------------------
char형
char형은 단일 바이트로 표현되는 가장 작은 데이터 단위로 정수를 표현하는 데이터 형이다.
이것은 부호있는(char) 형태와 부호 없는(unsigned char) 형태가 있는데
각기 표현가능한 수의 범위는 다음과 같다.

char                    -128 ~ 127
unsigned char      0 ~ 255
---------------------------------------------------------------------------------------
short 형
2바이트 메모리 공간을 차지하는 short 형은 역시나 
부호 있는 short 형과 없는 unsigned short 형으로 나뉘며 역시 정수를 표현한다.

short                    -32768 ~ 32767
unsigned short      0 ~ 65536
---------------------------------------------------------------------------------------
int형
가장 흔히 사용되는 기본 적인 정수 형 수를 표현하기 위해 제공되는 자료형으로
4바이트의 메모리 공간을 차지한다.
int형은 부호가 있는지 또는 없는지에 따라서 표현가능한 범위가 다르다.

부호 있는 int형의 경우

-2147483648 ~ 2147483647 까지의 정수를 표현할 수 있다.

부호 없는 int 즉 unsigned int형의 경우에는
0 ~ 4294967295 까지 표현이 가능하다.
---------------------------------------------------------------------------------------
long형
int 형과 마찬가지로 정수를 표현한다.
원래 16비트 시절 컴파일러에서는 int형의 경우 2바이트를 long형의 경우 4바이트 메모리 공간을 차지했지만
32비트 세대로 넘어 오면서 두개의 자료형은 같은 크기를 가지게 됐다.
그래서 32비트 컴파일러에서 실질적으로 int와 long형의 차이는 없다.
표현가능한 범위도 같다.
long형도 부호 있는 long과 없는 unsigned long형이 있다.
32비트 운영체제의 사용이 상당한 기간동안 지속되었기 때문에(현재까지도 쓰이고 있다.), int와 long을 별다른 의미없이 사용하는 프로그래머들이 상당히 많았다. 실질적으로 차이가 없음에 불가하고, 그냥 느낌상 좀 큰수를 표현하기 위해서는 long형을 사용해야만 할것같은 강박감... 아무튼 이것은 64비트 시대가 도래함에 따라 문제가 되게된다.
기존의 32비트 코드를 수정없이 그대로 64비트의 시스템에 이식하자니 주의 깊게 사용하지 않은 저런 자료형은 굉장한 골치거리가 된다.
특히나 프로그램의 덩치가 클수록 이런 문제는 더욱 심각하다.
물론 일일이 수정할 수는 있겠지만, 그과정에서 발생할 수 있는 의도치 않은 수많은 버그들은 생각만 해도 머리가 
지끈거린다.
아무튼 그런영향 때문인지 VC++컴파일러는(GCC 같은 것들은 다르다) 64비트로 넘어와서도 int와 long형의 자료크기가 여전히 4바이트로 유지되고 있다.
----------------------------------------------------------------------------------------------------
__bigint 형
다른 표준컴파일러들에는 없는 특이한 형태의 자료형이 있으니 그것은 __bigint형이다. 8바이트의 메모리 공간을 차지하고
있으며, 원래되로라면, 이녀석이 long형의 위치에 있어야 했지만 아무튼 vc++에서는 아예 64비트 정수를 표현하기 위한
자료형을 따로 만들었다.
표현가능한 범위는 음,,,, 계산하기 귀찮아서,,, 아무튼 엄청나다.
-------------------------------------------------------------------------------------------------------
float형
이때까지 나열한 기본 자료형들이 정수를 표현하는 역할을 했다면, 이녀석은 그와 다르게 실수를 표현하기위한 자료이다.
int형과 마찬가지로 4바이트 메모리 공간을 차지하는 float형은 정수부와 소수부를 표현하기 위한 특이한 구조를(부동소숫점) 통해서
실수 표현을 시뮬레이션 하고 있다.
실질적으로 float형은 실수표현을 흉내만 낼뿐 꾀나 큰 오차를 가진 자료형이다.
특히나 정밀한 실수 수치를 다뤄야 하는경우에는 오차 때문에사용하기 힘들다.
하지만 대부분의 경우에는 float형으로 실수 계산을 하기에 별 무리가 없다.
표현가능한 범위는 기억이 안난다.
아무튼 빠르게 실수 계산에 이용할 수 있는 가장 많이 쓰이는 자료형이다.
-------------------------------------------------------------------------------------------------------
double형
float형과 비슷하게 실수 표현에 사용되는 이자료형은 8바이트 길이를 가지며 float형보다 훨씬 높은 정밀도와
표현 범위를 가진다.
하지만 정밀도가 높아진 만큼 퍼포먼스문제가 있어, 32비트 시절에는 그렇게 자주 애용되는 자료형은 아니었던듯하다(지금은 다르겠지만).
꾀나 정밀한 연산을 해야할때 이용될수 있는 자료형이다. 하지만, 정말 엄청나게 정밀한 실수 연산에는 사용할 수 없다.
-------------------------------------------------------------------------------------------------------------------
bool형
c언어에는 없는 새로운 자료형으로 c++에서 논리적인 값을 표현하기 위해 사용된다.
true또는 false 중하나의 상태를 가질 수 있다.
vc++에서는 1바이트 공간을 차지한다.
--------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------
지금까지 기본자료형들에 대해서 알아봤다. 이제 포인터의 개념과 메모리의 구조에 대해서 알아보겠다.
먼저 메모리의 구조를 이해하게 되면 포인터에 대해서 쉽게 이해할 수 있게 된다.

메모리
오늘날의 컴퓨터들은 약간씩 구조에 차이는 있겠지만,
대부분은 연산을 위한 cpu, 연산의 명령또는 데이터를 저장하고 있는 메모리, 그리고 그것들의 소통로를 제공해주는 메인보드
그리고 그러한 연산의 결과들을 우리가 보거나 듣거나 만질 수 있게 표현해주는 각종 입출력 장치들로 구성되어 있다.

나머지 장치들을 제외하고 메모리 하드웨어에 대해서 간략히 알아보자.
실질적으로 메모리 하드웨어의 내부 구조가 어떻게 구성되는지는 메모리를 제조하는 제조사들마다 다를 테니 실질적인 물리적
구조를 논하는 것은 의미가 없을듯하다.
하지만 대부분의 메모리들은 논리적으로 다음과 같은 구조를 가지고 있다(반드시 그렇진 않지만 쉽게 생각하기 위해서 그렇다고 가정하자).

각 메모리들은 데이터를 저장하기 위한 셀들을 가지고 있다. 각셀들은 1바이트의 데이터를 저장한다.
이런셀의 개수가 몇개있는지에 따라서 메모리의 용량이 결정이 된다.
만일 10바이트 용량의 메모리가 있다고 가정해보자.
10바이트의 메모리에는
10개의 바이트를 저장하기위한 10개의 셀들이 나열되어 있을것이다.

위에 그림처럼 우리는 각셀들에 이름을 붙이기로 한다.
가장앞에 있는것은 0번 다음것은 1번 씩으로 이름을 순차적으로 하나씩 붙이기로한다.

이제 앞에서 5번째에 있는 셀에 1바이트를 저장한다고 해보자.
위에서 우리는 5번째 셀에 이름을 4로 붙였기 때문에 4번셀에 1바이트를 저장한다고 말할 수 있다.
이렇듯 우리는 어떤 기준점에 대해서 상대적인 위치를 부여 하는 즉 주소를 지정할 수 가 있는것이다.
어느동내의 어느위치에 몇번째 있는 집에 주소를 붙이듯이말이다.

포인터
C나 C++에서 포인터는 바로 위에서 설명한 주소를 가지고 있는 역할을 하는 변수 이다.
위의 예에서 앞에서 5번째에 있는 셀의 주소 즉 4라는 값을 포인터는 가지고 있게 되는것이다.
우리는 4번이라는 이름을 통해서 그게 어느 위치에 있는 셀인지를 식별할 수 있게된다.

컴퓨터의 모든 자료들은 메모리에 놓이게 되고 그것의 자료형 크기만큼 메모리 공간의 바이트를 차지하게 된다.
만일 short 형태의 어떤 자료가 메모리에 저장되어 있다고 가정해보자

short temp = 2;

이렇게 내가 선언한 변수가 위의 10바이트 메모리의 어떤 위치에 저장된다고 가정해보자.
short 형은 2바이트의 공간을 차지하기 때문에 10개의 셀중에서 2개의 셀을 차지하게 될것이다.
만일 temp변수가 앞에서 두번째 셀부터 저장이 된다면 temp변수는 1번과 2번셀을 차지하게 된다.

그리고 하나의 포인터를 선언해보자.
short* pt = &temp;
이렇게 pt라는 포인터에 temp변수의 주소를 할당하게 되면
포인터 pt는 temp변수가 위의 메모리 공간에서 저장된 첫번째 셀의 이름 값을 가지게 되는것이다.
이번의 예에서는 pt는 1이라는 셀의 이름을 가지게 될것이다.
즉포인터는 주소의 값을 저장하고 있는 변수이다.

포인터가 주소의 값을 저장하고 있는 변수라면 앞에 붙은 기본자료형은 대체 어떤 역할을 하는것일까?

byte*  int*, float* 등 다양한 형태의 기본자료형 또는 확장자료형(구조체나 클래스들)으로 포인터를
선언할 수 있다.
하지만 어떤 자료형의 포인터를 선언하더라도 포인터가 무언가의 주소를 가지고 있는 변수라는 
사실은 변하지 않는다.
포인터 선언에 사용된 자료형은 단지 포인터가 어떠한 자료형이 저장된 주소를 가지고 있는가를
나타낼뿐이다.
위의 예에서 short *pt로 선언된 pt포인터는 short형자료가 저장되어 있는 메모리의 주소를 가진다는 의미다.

2014년 5월 5일 월요일

iOS 사파리 브라우져를 열어서 특정 사이트로 이동하기

 던전워즈
게임내에서 게임의 공식 카페나, 또는 앱 다운로드가 가능한 iTunes 스토어로 이동하기위해서
아래와 같은 방법을 사용하면 된다.
인자로 이동할 사이트의 url을 주면 사파리 브라우져가 열리면서 주어진 사이트로 이동된다.

static NSString* CreateNSString(const char* string)
{
    if (string != NULL)
        return [NSString stringWithUTF8String:string];
    else
        return [NSString stringWithUTF8String:""];
}
void iOsGotoHomepage(const char* strURL)
{
    NSString* pURL = CreateNSString(strURL);
    NSURL *url = [NSURL URLWithString:pURL];
    [[UIApplication sharedApplication] openURL:url];
}

유니티 iOS 플러그인 만들기

 던전워즈
유니테에서 iOS의 네이티브 함수를 호출하기 위해서 다음과 같은 방법으로 통신할 수 있다.


public class iOSManager : MonoBehaviour
{
    static iOSManager _instance = null;

    [DllImport("__Internal")]
    private static extern void iOsFunction(string strMessage);

//iOS의 네이티브 함수를 호출한다. 인자로 strMsg라는 문자열을 넘긴다.
public void CallIosFunction(string strMsg)
{
iOsFunction(strMsg);
}


//이후에 iOS의 네이티브 단에서 이 메소드를 호출한다.
//유니티에서는 단지 iOS에서 넘어온 문자열을 유니티 콘솔에 출력해준다.
public void MsgFromiOs(string strMsg)
{
MonoBehaviour.print("msg from ios : " + strMsg);
}
}

유니티 단에서는 위와 같이  [DllImport("__Internal")] 선언을 하고 아래에 함수를 외부로 부터 가져온다고 알린다.
이후에는 일반 적인 c#의 메소드를 호출하듯이 호출해주면된다.
iOS네이티브 단에서는 위에서 선언한 함수를 실제 구현해줘야한다.


iosplugin.m 이라는 소스 파일을 하나 만들고
내부에 위의 c#스크립트에서 선언했던 형태로 함수를 구현해준다.
c#의 스트링은 iOS에 인자로 넘어올때 UTF-8의 바이트 배열 형태로 변환되어 넘어오기 때문에
인자를 const char* 형태로 바꿔준다.

//utf-8의 char형 배열은 아래 함수를 통해서 NSString으로 변환가능하다.

static NSString* CreateNSString(const char* string)
{
    if (string != NULL)
        return [NSString stringWithUTF8String:string];
    else
        return [NSString stringWithUTF8String:""];
}

void void iOsFunction(const char* strMessage)
{
//단순히 유니티로 부터 전달받은 메시지를 오브젝트c의 NSString으로 변환하고 그것을 다시 utf-8의 char형 배열로 변환한다음에
//다시 유니티로 전달하는 것을 보여준다.
   NSString* strResult = CreateNSString(strMessage);

//안드로이드에서와 비슷하게 UnitySendMessage함수를 통해서 유니티의 특정 오브젝트에 연결된 스크립트를 호출할 수 있다.
//c#의 스크립트에서 스트링으로 넘어온 문자열이 오브젝트 c에서 UTF-8의 char형배열로 변환된것처럼
//오브젝트c에서 NSString 문자열을 유니티로 넘길때에도 UTF-8의 char 형배열로 변환해서 넘기면된다.
//이호출을 통해서 위의 c#스크립트에서 구현해놓은 MsgFromiOs메소드가 호출되게 된다.
    UnitySendMessage("iOSManager", "MsgFromiOs", [strResult UTF8String]);

}