Library2016. 12. 7. 16:43

C++ 과 유니티 를 연동해서 사용하려면 먼저 알아 두어야 할 것이 있다.

 

유니티는 C# 을 지원 하기 위해 MonoDevlop 을 사용 한다.

Unity 탑재된 MonoDevlop 버전은 2.6 이고 .Net 버전 3.5 와 매칭 된다.

 

이 말은 .Net 3.5 에서 지원하지 않는 것은 Unity 에서도 지원하지 못한다는 의미이다.

 

% 유니티를 사용 계획이 없는 C++, C# 간의 연동이라면 최상위 버전의 ProtoBuf 를 사용하면 된다.

적용 방법이 약간 다르지만 다운 받은 ProtoBuf 의 ReadMe 파일을 보면 빌드에 필요한 라이브러리, 빌드 방법이 친절히 설명 되어 있다.

 

사용한 Tool 은 Visual Studio 2010 이다.

 

Proto 파일을 *.h, *.cs 파일로 변환

 

C# 3.5 를 지원 하는 ProtoBuf 바이너를 다운 받는다. (https://code.google.com/archive/p/protobuf-net/downloads)

% 최상위의 protobuf-net r668.zip 버전을 받는다.

% 해당 버전은 서드파티에서 지원하는 것이고 해당 버전에서는 공식적으로 C#을 지원하지 않았다.

 

 

압축을 풀고

protobuf-csharp-port-master\src\ProtoGen 프로젝트를 빌드 한다.

protobuf-csharp-port-master\src\ProtocolBuffersLibrary.NET35.sln 을 열어서 빌드 한다.

 

protobuf-csharp-port-master\lib\protoc.exe 는 addressbook.proto 파일을 addressbook.pb.cc, addressbook.pb.h 로 변환 한다.

 

ProtoGen.exe 는 addressbook.proto 파일을 Addressbook.cs 로 변환 한다.

% Google.ProtocolBuffers.dll (ProtoGen 빌드 결과)

% ProtoGen.exe (ProtocolBuffersLibrary.NET35.sln  빌드 결과)

 

변환된 두 파일을 프로젝트에 포함 하여 사용 하면된다.

 

변환 명령 커맨드는 배치 파일로 만들어 다음과 같이 사용 하였다.

 

set CPP_DST_DIR=.\cpp
set CSHARP_DST_DIR=C:\Users\youngmoon\Desktop\PROTO-BUF\sample\protocol\csharp
set SRC_DIR=.\proto

 

protoc -I=%SRC_DIR% --cpp_out=%CPP_DST_DIR% %SRC_DIR%/addressbook.proto
ProtoGen.exe %SRC_DIR%/addressbook.proto -output_directory=%CSHARP_DST_DIR%

 

 

C# 프로젝트 연동

 

 

빌드 결과 는 protobuf-csharp-port-master\src\ProtocolBuffers\bin\NET35\ 에 생성된 Debug, Release 폴더 안에 있다.

 

신규 프로젝트를 생성하고 빌드된 DLL 을 사용하여 작업을 한다.

 

 

 

 

C++ 프로젝트 연동

 

C# 버전과 호환 되는 C++ 소스를 다운 로드 받는다.

 

https://github.com/google/protobuf/releases?after=v2.6.1 에서 protobuf-2.4.1.zip 를 다운 받는다.

 

압축을 풀고 protobuf-2.4.1\vsprojects\protobuf.sln 프로잭트를 연다.

libprotobuf 프로젝트를 빌드 한다. 빌드 할때 "일반 - 문자집합", "C/C++ - 코드생성 - 런타임 라이브러리" 속성을 맞춘다.

% 나는 멀티 바이트, MT, MDT 로 설정 하였다. 해당 라이브러리를 사용할 프로젝트에도 맞춰야 한다.

 

신규 프로 잭트를 생성하여 라이브러리 헤더 파일 경로를 맞추고 작업을 진행 한다.

 

 

 

 

 

Posted by 상현달
Library2012. 9. 28. 09:30

응용프로그램에서 데이타베이스를 인베디드 시키려면 DB 를 동작할수 잇게 해주는 라이브러리가 필요하다.

 

크게 두가 지가 제일 유명한 것 같다.

 

구글의 LevelDB 와 SQLite 이다.

 

LevelDB 는 key-Value 방식으로 사용된다 NoSQL 이다.

 

나는 SQL 이 필요하기 때문에 SQLite 를 사용하기로 했다.

 

SQLite 를 응용프로그램에 인베디드 시키는 방법을 소개한다.

 

 

 

1, 먼저 SQLLite 라이브러리를 다운로드 받는다. 다운로드

    sqlite-amalgamation 를 다운받고 압축을 푼다.

 

2, 압축을 풀면 *.lib 파일이 없다 *.def 파일을 이용해서 *.lib 파일을 만든다.

 

  정상적으로 실행 됐따면 sqllite3.lib, sqllite.exe 가 생성 되었을 것이다.

 

  % 수행중에 "mspdb80.dll" 를 찾을 수 없다는 메시지가 나온다면 환경변수 "path" 에

      "C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\IDE" 경로를 추가하면 된다.

 

3, 이제 생성된 라이브러리를 사용 합니다.

 

 

 

typedef int SQLITE_RESULT;

#include "SQLLite/sqlite3.h"

#pragma comment(lib, "sqllite/sqlite3.lib")

int _tmain(int argc, _TCHAR* argv[])
{
	sqlite3 *db = NULL;

	SQLITE_RESULT sr = sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
	
	if(sr != SQLITE_OK)
	{
		printf("open fail (%s)", sqlite3_errmsg(db));
		return 0;
	}

	char* err_msg		= NULL;
	sqlite3_stmt *stmt	= NULL;

	const char* const query_table  = "CREATE TABLE TEST (test_column INTEGER)";
	const char* const query_insert = "INSERT INTO TEST VALUES (99)";	
	const char* const query_select = "SELECT * FROM TEST";

	sr = sqlite3_exec(db, query_table,  NULL, 0, &err_msg);
	sr = sqlite3_exec(db, query_insert, NULL, 0, &err_msg);

	sr = sqlite3_prepare(db, query_select, strlen(query_select), &stmt, NULL);

	while ( sqlite3_step(stmt) == SQLITE_ROW )
	{
		printf("test_cloum: %d\n", (int)sqlite3_column_int(stmt, 0));
	}

	sqlite3_finalize(stmt);
	sqlite3_free(err_msg);
	sqlite3_close(db);
	
	return 0;
}

Posted by 상현달
Library2012. 9. 13. 20:19

오라클 클라이언트 없이 ODBC 를 설정할 수 있다.

바로 시작해 보자

 

 1, 먼저 오라클 홈페이지에서 다음을 다운로드 받는다.  링크

"다운로드 - Oracle Instant Client - 해당 OS 버전 선택" 후에

"Instant Client Package - Basic", "Instant Client Package - ODBC" 두개를 다운 로드 받는다.

 

2, "Instant Client Package - Basic" 파일은 압축을 풀고 로컬("C:\instantclient_11_2")에 복사 한다.

3,  "Instant Client Package - ODBC" 파일은 압축을 풀고 "odbc_install.exe" 를 실행한다.

 

4, 환경 변수를 등록 한다.

"컴퓨터 (오른쪽 마우스) - 속성 - 고급 시스템 설정 - 고급텝 의 환경 변수"

  • Path: C:instantclient_11_2
  • NLS_LANG: KOREAN_KOREA.AL32UTF8
  • ORACLE_HOME: C:\instantclient_11_2
  • TNS_ADMIN: C:\instantclient_11_2
  •  

     

    5, "C:\instantclient_11_2" 폴더에 메모장으로 다음의 내용을 저장하고 파일명을 "tnsnames.ora" 만든다.

     ORCL=
    (DESCRIPTION=
     (ADDRESS_LIST=
     (ADDRESS=(PROTOCOL=TCP)(HOST=10.1.1.1)(PORT=1521))
     )
     (CONNECT_DATA=
     (SERVER=DEDICATED)
     (SERVICE_NAME=XE)
     )
    )

    % SERVICE_NAME 을 알고 싶으면 "select name from v$database" 쿼리를 수행 한다.

    6, 여기 까지 잘 따라 왔다면 이제 ODBC 추가에서 다음과 같은 항목이 보인다.

     


    7, "마침" 버튼을 클릭 하여 세부 항목을 작성한다.

     

    Data Source Name: 표시되는 이름 (보기 편한 이름 아무거나 쓴다)

    Description: 생략 가능

    TNS Service Name: 5번에서 작성한 이름이다.

    User ID: 오라클 서버에 접속 가능한 계정

    % Test Connection 버튼을 클릭하여 패스워드를 입력하고 서버에 접속 테스트를 한다.

    Posted by 상현달
    Library2012. 1. 5. 18:12

    CPPUNIT 이후 C++ 테스트 프레임웍 중 최고로 평가 되는 구글테스트, 구글목테스트 사용기 이다.
    머 사실 선택의 폭이 그리 넓지 않다는 ...

    구글 테스트는 C 타입의 함수타입 이고, 구글목 테스트는 C++ 객체 타입이라고 이해하면 이해가 빠르것 같다.

    구글목은 테스트 프레임웍이 아니라 구글테스트의 확장이므로 구글테스트도 같이 필요하다.
    구글목 테스트를 설치 하면 구글 테스트도 같이 설치된다.

    1, 먼저 구글목 테스트 프레임웍을 다운받는다. http://code.google.com/p/googlemock/

    2, 다음 Visual C++ 로 구글목 테스트를 빌드 한다. "gmock\msvc\2005\gmock"

    3, 빌드를 하면 오류가 발생할 것이다. 구글목은 tr1 의 tuple 를 사용하기 때문에 boost 를 설치해 준다. http://extern.tistory.com/37

    4, 설치한 boost 의 경로를 include 폴더에 추가한다. "boost_version", "boost_version\boost\tr1\tr1"

    5, 신규 프로젝트를 만들어서 구글목 헤더를 폴더에 추가한다.  "mock\gtest\include", "gmock\include"

    나머지는 소스로~

    #include 
    
    #if defined (_DEBUG)
    	#pragma comment (lib, "2005/Debug/gmock.lib")	
    #else
    	#pragma comment (lib, "2005/Release/gmock.lib")	
    #endif
    
    
    /*start: 메소드 테스트*/
    
    int ReturnMethod()
    {
    	return 1;
    }
    
    //MethodTest, True_Method 는 결과창에서 구분을 위한 설명
    TEST(MethodTest, True_Method)
    {
    	EXPECT_EQ(ReturnMethod(),1);		
    }
    
    TEST(MethodTest, False_Method)
    {
    	EXPECT_EQ(ReturnMethod(),2);		
    }
    
    /*end:  메소드 테스트*/
    
    
    
    /*start: class 테스트*/
    
    // ::testing::Test 상속 받아야 한다.
    class Test_Class : public ::testing::Test
    {
    public:	
    	// TEST_F 통해 class를 테스트 할때 실행되는 함수
    	virtual void SetUp()
    	{
    		test_ptr = new int;
    	}
    	// TEST_F 통해 class를 테스트 할때 마지막에 실행되는 함수
    	virtual void TearDown()
    	{
    		delete test_ptr;
    		test_ptr = NULL;
    	}
    
    	//SetUp(), TearDown() 는 기본 생성자 소멸자로 대체 가능하지만 그렇게 사용하지 말자
    		
    protected:
    	int* test_ptr;
    };
    
    TEST_F(Test_Class, True_Class)
    {
    	ASSERT_TRUE(test_ptr != NULL);
    }
    
    TEST_F(Test_Class, False_Class)
    {
    	ASSERT_FALSE(test_ptr != NULL);
    }
    
    /*end: class 테스트*/
    
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	testing::InitGoogleMock(&argc, argv);
    	return RUN_ALL_TESTS();
    }
    
    

     

     

    Posted by 상현달
    Library2010. 11. 23. 19:22

    function 은 함수를 일반 변수처럼 사용 가능하게 해준다.

    #include "stdio.h"
    #include "iostream"
    
    #include "functional"
    using std::tr1::function;
    using std::type_info;
    
    void print_type(const type_info& info)
    {
        std::cout << info.name() << std::endl;
    }
    
    void main(void)
    {	
       //_CRTIMP int __cdecl atoi(const char *)
       function func_atoi(atoi);
       function func_empty;
    
       //함수 타입 출력
       print_type(func_atoi.target_type());
       print_type(func_empty.target_type());
    
       //bool operator 이 정의 되어 있어서 바로 비교 가능하다.
       if(!func_atoi)
    	std::cout << "func_atoi is null" << std::endl;	
    
       if(!func_empty)
    	std::cout << "func_empty is null" << std::endl; 
    
       int num = func_atoi("12345");                       
       std::cout << "Number is " << num << std::endl;
    
    
       func_empty.swap(func_atoi); // func_atoi.swap(func_empty); 도 같은 결과이다.
    
       if(!func_atoi)
            std::cout << "func_atoi is null" << std::endl;	
    
       if(!func_empty)
            std::cout << "func_empty is null" << std::endl; 
        
    }
    

    출력결과:
    int (__cdecl*)(char const *)
    void
    func_empty is null
    Number is 12345
    func_atoi is null
    Press any key to continue
    보너스로 bind() 간단한 예제
    #include "iostream"
    
    using std::cout;
    using std::endl;
    
    #include 
    
    using std::tr1::function;
    using std::tr1::bind;
    
    template 
    void Func_call(FUNC func)
    {
        cout << func("1234") << endl;
    }
    
    void main()
    {
        function func(atoi);
        Func_call(func);
        Func_call(bind(atoi, _1));
    }
    
    Posted by 상현달