반응형
./a.out & 
무한루프 돌아가도록 코드 만든 후
ps 로 PID확인후
pmap PID하면 나옴
 
반응형
반응형
C, C++언어에서

인라인 장점 : 속도가 빠르다
인라인 단점? : 목적 코드가 커진다.? 아니다 작은 코드라면 목적코드도 작아진다

모든 compiler는 인라인은 default로 무시, 옵션켜야만 inline이 치환된다

cl inline.cpp /Ob1 인라인 치환해달란 옵션 

debugging할때는 어려울 수 있다. call이 안보이니까
그러면 개발은 inline옵션 안넣고 release시 inline옵션 넣으면? 된다

inline int Add1(int a, int b) {return a + b;}
int Add2(int a, int b) {return a + b;}

int main()
{
int a = 1, b = 2;
int n1 = Add1(a, b); // 기계어 코드 치환
int n2 = Add2(a, b); // 호출 즉 call
}


/////////////////////////////////////
; 13   : int n1 = Add1(a, b); // 기계어 코드 치환

mov eax, DWORD PTR _a$[ebp]
add eax, DWORD PTR _b$[ebp]
mov DWORD PTR _n1$[ebp], eax

; 14   : int n2 = Add2(a, b); // 호출 즉 call

mov ecx, DWORD PTR _b$[ebp]
push ecx
mov edx, DWORD PTR _a$[ebp]
push edx
call ?Add2@@YAHHH@Z ; Add2
add esp, 8
mov DWORD PTR _n2$[ebp], eax
 


반응형
반응형
어셈으로 살펴보는 함수 call의 원리
     java는 __stdcall이라는 방식을 사용합니다.
     java와 C가 통신하려면 __stdcall방식을 아셔야 합니다.

www.nasm.us 에서 download에서 win최신 버전을 설치한다
nasm -f win32 -o 1.obj 1.asm 

////////////////////////////////////////
// main.c

#include <stdio.h>

int asm_main();

int main()
{
int n = asm_main();
printf("result = %d\n", n);
return 0;
}
 
; 3. asm - 함수의 인자 전달 방식
; 1. 레지스터를 사용한 인자 전달 - 빠르다!! 하지만 갯수의 제약이 있다.
; 2. 스택을 사용한 인자 전달 - 인자 전달에 사용한 스택을 파괴해야 한다.
; (1) 호출자 파괴
; (2) 호출당한자 파괴 - 시스템에 안정적이고 메모리 사용량이 약간 줄어 든다

segment .text

global _asm_main
_asm_main:
; 레지스터를 사용한 인자의 전달.
mov edx, 2
mov ecx, 1
call foo
; 스택을 사용한 인자 전달
push 5
push 8
call goo ; 돌아올 주소를 스택에 넣는다( push 돌아올 주소 \ jmp goo)
add esp, 8 ; 인자 전달에 사용한 스택을 파괴해야 한다
ret
goo: ; 인자를 꺼내야 한다. 어떻게?? 잘 생각해보자
mov eax, dword[esp+4]
add eax, dword[esp+8]
ret
foo:
mov eax, ecx ;eax = ecx
add eax, edx ;eax += edx
ret
 








#include <stdio.h>

void __stdcall foo(int a, int b)
{
printf("foo\n");
}

//함수 포인터와 Calling Convention문제
//typedef void(*F)(int, int);   // 이렇게 하면 _cdecl로 함수포인터가 동작한다. 여기에 __stdcall함수를 넣으면 stack이 2번 파괴됨
typedef void(__stdcall *F)(int, int) ; //이렇게 해야 맞다

int main()
{
F f = (F)&foo;
f(1,2); //어떻게 될까요? 정확하게 어떤 현상이 나올 지 정확히 예측가능해야 함
// push 2
// push 1
// call foo
// add esp, 8
// 결국은 stack이 2번 파괴됨
반응형
반응형
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
using namespace android;


#include "ICalc.h"

// 클라이언트는 BpCalc를 알 필요가 없다.
// 알면 안된다. 
// 이거는 이제 이거 다 되고 나면 Stub에서 설명하며 개선해 나갈듯


int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> svc = sm->getService(String16("myserver1"));

    //아래 캐스팅을 하는 순간 ICalc::asInterface()를 호출하는 데 결국 거기서 BpCalc객체가 생성된다.
    //즉 , new BpCalc(svc)가 된다. 
    sp<ICalc> pCalc = interface_cast<ICalc>(svc);
    int ret = pCalc->Add(1,2);

    printf("result : %d\n", ret);

    return 0;
}


//BpCalc.h
#ifndef _BPCALC_H_
#define _BPCALC_H_

#include "ICalc.h"

class BpCalc : public BpInterface<ICalc>
{
public:
    BpCalc( const sp<IBinder>& binder);
    virtual int Add(int a, int b);
    virtual int Sub(int a, int b);

};


#endif //_BPCALC_H_
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>

using namespace android;

#include "BpCalc.h"
BpCalc::BpCalc(const sp<IBinder>& binder) : BpInterface<ICalc>(binder)
{
}

int BpCalc::Add(int a, int b)
{
    Parcel data, reply;
    data.writeInt32(a);
    data.writeInt32(b);
    int ret = remote()->transact(ADD, data, &reply);
    return reply.readInt32();
}

int BpCalc::Sub(int a, int b)
{
    Parcel data, reply;
    data.writeInt32(a);
    data.writeInt32(b);
    int ret = remote()->transact(SUB, data, &reply);
    return reply.readInt32();
}

//
IMPLEMENT_META_INTERFACE(Calc, "myserver1") //asInterface imple




//ICalc.h

#ifndef _ICALC_H_
#define _ICALC_H_
enum {
    ADD = IBinder::FIRST_CALL_TRANSACTION,
    SUB,
};

class ICalc : public IInterface
{
public:
    virtual int Add(int a, int b) = 0;
    virtual int Sub(int a, int b) = 0;

    DECLARE_META_INTERFACE(Calc)
};
#endif //_ICALC_H_

반응형
반응형
// froyo/external/여러분폴더/0321/binder3폴더를 만들고 myclient3.cpp로 만드세요

#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
using namespace android;

enum { ADD = IBinder::FIRST_CALL_TRANSACTION,
  SUB 
     };

// 모든 Proxy를 만들때 공통으로 사용되는 부분은 부모로 뽑아서 사용하자.
class myBpRefBase : public virtual RefBase
{
sp<IBinder> mRemote;
public:
myBpRefBase( const sp<IBinder>& binder ) : mRemote(binder) {}

sp<IBinder> remote() const { return mRemote; }
};

// 이제 서버의 진짜 calc나 클라이언트의 Proxy를 만들때 공통으로 사용할 인터페이스를 
// 먼저 설계하자.
class ICalc : public virtual RefBase
{
public:
virtual int Add(int a, int b ) = 0;
virtual int Sub(int a, int b ) = 0;

virtual IBinder* asBinder() const = 0;

static sp<ICalc> asInterface( const sp<IBinder>& binder );  // static이므로 순수 가상함수일수는 없다.
// 그냥 선언만 하자.!!
};

// 이제 모든 Proxy는 자신의 인터페이스와 BpRefBase에서 파생되어야 한다.
class BpCalc : public ICalc, public myBpRefBase
{
public:
BpCalc( const sp<IBinder>& binder) : myBpRefBase( binder ) {}
int Add( int a, int b) 
{
Parcel data, reply;
data.writeInt32(a);
data.writeInt32(b);
remote()->transact( ADD, data, &reply); // source ~/froyo/build/envsetup.sh

return reply.readInt32();
}
int Sub( int a, int b) 
{
Parcel data, reply;
data.writeInt32(a);
data.writeInt32(b);
remote()->transact( SUB, data, &reply);

return reply.readInt32();
}
// Android.mk 파일 만드세요.
// 객체를 바인더로 변경하는 함수 // 빌드하세요..
IBinder* asBinder() const // myserver1 띄우고 실행해보세요
{
return remote().get();
}
};
// 바인더를 객체로 변경하는 함수
// 이제 이함수는 ICalc의 멤버 함수이다.
sp<ICalc> ICalc::asInterface( const sp<IBinder>& binder )
{
return new BpCalc( binder);
}

int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> svc = sm->getService(String16("myserver1"));

sp<ICalc> p = ICalc::asInterface(svc);

return 0;
}
// C   : 결국 서비스번호(핸들)을 얻게 되고 binder_call()함수 사용=> 결국 ioctl()함수로
// 드라이버를 통해서 서버와 통신.

// C++ : sm->getService()하는 순간 BpBinder라는 객체가 생성되고 포인터를 리턴 받는다.
//       바인더->transact()함수를 사용해서 서버와 통신

// Proxy : Calc를 설계하고 Add(), Sub()함수를 제공한후에 바인더는 Calc의 내부로 감춘다.












//C라면 : 결국 서비스 번호(핸들)을 얻게 되고 binder_call()함수 사용 => 결국 ioctl()함수로 드라이버를 통해서 서버와 통신.

// C++은? : sm->getServeice()하는 순간 BpBinder라는 객체가 생성되고 포인터를 리턴 받는다.
                 바인더->transact()함수를 사용해서 서버와 통신
                 바인더를 바로 쓰려면 그 번호 다 알아서 써야 하고 불편(좋은 방법은 아님)
                 최종적으로 가져다 쓰는 사람입장에서 쉽고 실수하지 않도록 member함수처럼 만들어주면 좋겠다-> proxy 
                 실제 그 멤버는 실제 transaction 을 사용( information 은닉, interface노출)
// proxy는? : Calc를 설계하고 Add(), Sub()함수를 제공한 후에 바인더는 Calc의 내부로 감춘다.

 

#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
using namespace android;

// Interface //////////////////////////////////////
// management binder
class myBpRefBase : public virtual RefBase
{
    sp<IBinder> mRemote;
public:
    myBpRefBase( const sp<IBinder>& p) : mRemote(p) {}

    sp<IBinder> remote() const { return mRemote; }
};

//parents of  all interface
class myIInterface : public virtual RefBase
{
public:
    IBinder* asBinder() { return OnAsBinder(); }

protected:
    virtual IBinder* OnAsBinder() = 0;
};

// interface of all user must have as Interface()
#define MY_DECLARE_META_INTERFACE(INTERFACE) \
            static sp<I##INTERFACE> asInterface(const sp<IBinder>& binder);

#define MY_IMPLEMENT_META_INTERFACE(INTERFACE, description)                     \
            sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& binder)\
            {                                                                   \
                return new Bp##INTERFACE(binder);                               \
            }

//1. we do not want implement on OnAsBinder() every BpClass
//2. multiple inheritance to mono inheritance
template<typename INTERFACE>
class myBpInterface : public INTERFACE, public myBpRefBase
{
public:
    myBpInterface(const sp<IBinder>& binder) : myBpRefBase(binder) {}
protected:
    virtual IBinder* OnAsBinder() {return remote().get(); }
};

/////////////////////////////////////////////////

enum {
    ADD = IBinder::FIRST_CALL_TRANSACTION,
    SUB
};


class ICalc: public myIInterface
{
public:
    virtual int Add(int a, int b) = 0;
    virtual int Sub(int a, int ) = 0;

    MY_DECLARE_META_INTERFACE(Calc)
    //static sp<ICalc> asInterface(const sp<IBinder>& binder);
};

class BpCalc : public myBpInterface<ICalc>
{
public:
    virtual int Add(int a, int b) {
        Parcel data, reply;
        data.writeInt32(a);
        data.writeInt32(b);
        remote()->transact( ADD, data, &reply); // source ~/froyo/build/envsetup.sh

        return reply.readInt32();
    }
    virtual int Sub(int a, int b) {
        Parcel data, reply;
        data.writeInt32(a);
        data.writeInt32(b);
        remote()->transact( SUB, data, &reply); // source ~/froyo/build/envsetup.sh
        return reply.readInt32();
    }
//protected:
//  virtual IBinder* OnAsBinder() {return remote().get(); }
};

MY_IMPLEMENT_META_INTERFACE(Calc, "calc.com")
//sp<ICalc> ICalc::asInterface( const sp<IBinder>& binder )
//{
//  return new BpCalc( binder);
//}





int main(int argc, char** argv)
{
    return 0;
}


 
반응형
반응형
const 이야기..
상수 함수.!!
 
class Point
{
public:
int x,y;
Point(int a = 0, int b = 0) : x(a), y(b) {}
void Set(int a, int b) {x = a; y = b;}
void print() const //상수함수, 컴파일러에게 멤버 바꾸는게 없다는 것을 보장해서 알려주는 것
{
cout << x << ", " << y << endl; // read 는 가능..
}
};

int main()
{
const Point p(1,2);
p.x = 10; // error 나야하고 맞음
p.Set(10, 20); // const니가 error나야 하고 맞음
p.print(); //될까? 되야 할까? 안되야 할까? 되야 하죠
          // print()가 상수함수여야만 가능하다.

또 다른 예)
이동하지 못하는 사각형을 만든다면 그 사각형의 면적도 구할 수 없어야 할까요?
면적은 이동하지 못하는 사각형이라도 할 수 있어야 함
면적 구하는 함수는 상수함수로 만든다

//중요~~~
멤버 함수가 멤버변수를 바꾸는게 없으면 무조건 꼭 const를 붙여야 한다.
}

반응형
반응형
############
//myserver0.c
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <errno.h>
  4 #include <unistd.h>
  5 #include <fcntl.h>
  6 #include <sys/mman.h>
  7 #include "binder.h"
  8
  9 // myserver0.c
 10 //
 11 struct binder_state
 12 {
 13     int fd;
 14     void* mapped;
 15     unsigned mapsize;
 16 };
 17
 18 unsigned token;
 19
 20 //do something to do because It is server
 21 int Add(int a, int b)
 22 {
 23     printf("Add(%d, %d)\n", a, b);
 24     return a + b;
 25 }
 26
 27 int my_handler(struct binder_state* bs,
 28         struct binder_txn* txn,
 29         struct binder_io* msg,
 30         struct binder_io* reply)
 31 {
 32     int ret, a, b;
 33     switch(txn->code)
 34     {
 35         case 1:
 36             a = bio_get_uint32(msg);
 37             b = bio_get_uint32(msg);
 38             ret = Add(a, b);
 39             bio_put_uint32(reply, ret);
 40             return 0;
 41     }
 42     return 0;
 43 }
 44
 45
 46 int main()
 47 {
 48     int mapsize = 1024 * 128;
 49     struct binder_state* bs;
 50
 51     unsigned int status;
 52     char iodata[512];
 53     struct binder_io msg;
 54     struct binder_io reply;
 55
 56     // --------------------------------------------------------------
 57     // 1. binder driver open
 58     //bs = malloc(sizeof(struct binder_state));
 59     //bs->fd = open("/dev/binder", O_RDWR);
 60     //bs->mapsize = mapsize;
 61     //bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
 62     bs = binder_open(mapsize);
 63
 64
 65     // --------------------------------------------------------------
 66     // 2. add service
 67     bio_init(&msg, iodata, sizeof(iodata), 4);
 68
 69     //
 70     bio_put_string16_x(&msg, SVC_MGR_NAME);
 71     bio_put_string16_x(&msg, "myserver0");
 72     bio_put_obj(&msg, &token);
 73
 74     if(binder_call(bs, &msg, &reply, BINDER_SERVICE_MANAGER, SVC_MGR_ADD_SERVICE))
 75     {
 76         printf("error register service\n");
 77         return -1;
 78     }
 79     status = bio_get_uint32(&reply);
 80
 81     binder_done(bs, &msg, &reply);
 82     //3. binder loop
 83     binder_loop(bs, my_handler);
 84
 85
 86
 87
 88     return 0;
 89 }
 



//myclient0.c
   1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <errno.h>
  4 #include <unistd.h>
  5 #include <fcntl.h>
  6 #include <sys/mman.h>
  7 #include "binder.h"
  8
  9 int main(int argc, char** argv)
 10 {
 11     void* ptr;    //var that get service no on server
 12     struct binder_state* bs;
 13     struct binder_io msg, reply;
 14     char iodata[512/4];
 15     int ret;
 16
 17     //1. driver open and make receive ber
 18     bs = binder_open(128*1024); // 128k receive buffer
 19
 20     //2. make packet that will send service manager
 21     // work on binder_io but eventually send to driver as binder_write_read
 22     bio_init(&msg, iodata, sizeof(iodata), 4);
 23     bio_put_string16_x(&msg, SVC_MGR_NAME); // "android.os.IServiceManager"
 24     bio_put_string16_x(&msg, argv[1]);
 25
 26     if(binder_call(bs, &msg, &reply, BINDER_SERVICE_MANAGER, SVC_MGR_CHECK_SERVICE))
 27     {
 28         printf("can't find service : %s\n", argv[1]);
 29         return -1;
 30     }
 31     ptr = bio_get_ref(&reply);
 32
 33     printf("find service handle : %d\n", ptr);
 34
 35     //3. request add function
 36     memset(&msg, 0, sizeof(msg));
 37     memset(&iodata, 0, sizeof(iodata));
 38     memset(&reply, 0, sizeof(reply));
 39
 40     bio_init(&msg, iodata, sizeof(iodata), 4);
 41     bio_put_uint32(&msg, 3);
 42     bio_put_uint32(&msg, 4);
 43
 44     if(binder_call(bs, &msg, &reply, ptr, 1))
 45     {
 46         printf("can't request : %s\n", argv[1]);
 47         return -1;
 48     }
 49     ret = bio_get_uint32(&reply);
 50     printf("result = %d\n", ret);
 51
 52     //-----------------------------------------
 53     binder_done(bs, &msg, &reply);
 54
 55     return 0;
 56 }
 57
 58


==============================================================================================================
cpp로

//myserver1.cpp
      서버의 기본 흐름
       1. 반드시 BBinder 클래스의 자식클래스로 만들어야 합니다.
       2.  
  3 #include <sys/types.h>
  4 #include <unistd.h>
  5 #include <grp.h>
  6 #include <binder/IPCThreadState.h>
  7 #include <binder/ProcessState.h>
  8 #include <binder/IServiceManager.h>
  9 #include <utils/Log.h>
 10 using namespace android;
 11
 12 enum {
 13     ADD = IBinder::FIRST_CALL_TRANSACTION,
 14     SUB,
 15 };
 16
 12 class Calc : public BBinder
 13 {
 14     public:
 15         int Add(int a, int b)
 16         {
 17             printf("Calc.Add(%d, %d)\n", a, b);
 18             return a + b;
 19         }
 15         int Sub(int a, int b)
 16         {
 17             printf("Calc.Sub(%d, %d)\n", a, b);
 18             return a - b;
 19         }
 21         virtual status_t onTransact(uint32_t code, // service code
 22                                     const Parcel& data, // data that client sent
 23                                     Parcel* reply,      // place that will send return value
 24                                     uint32_t flags = 0)
 25         {
 26             int ret;
 27             int a = data.readInt32();
 28             int b = data.readInt32();
 29
 30             switch(code)
 31             {
 32                 case ADD: ret = Add(a, b);
 33                         reply->writeInt32(ret);
 34                         break;
 32                 case SUB: ret = Sub(a, b);
 33                         reply->writeInt32(ret);
 34                         break; 
 35             }
 36             return 0;
 37         }
 38 };
 39
 40 int main(int argc, char** argv)
 41 {
 42     sp<ProcessState> proc(ProcessState::self()); // code that we learn yesterday.
 43     sp<IServiceManager> sm = defaultServiceManager();
 44     sm->addService(String16("myserver1"), new Calc); //Calc 객체가 token대신 들어가게 됩니다.
 45     IPCThreadState::self()->joinThreadPool(); // 이 순간 enter the loop
 46
 47     return 0;
 48 }
 49




//myclient1.cpp
  1 #include <sys/types.h>
  2 #include <unistd.h>
  3 #include <grp.h>
  4 #include <binder/IPCThreadState.h>
  5 #include <binder/ProcessState.h>
  6 #include <binder/IServiceManager.h>
  7 #include <utils/Log.h>
  8
  9 using namespace android;
 12 enum {
 13     ADD = IBinder::FIRST_CALL_TRANSACTION,
 14     SUB,
 15 };
 
 11 int main(int argc, char** argv)
 12 {
 13     sp<ProcessState> proc(ProcessState::self());    //드라이버 오픈 // 수신버퍼 생성 // IPCThreadState와는 Friend관계
         // 서비스 매니저를 래핑하는 클래스가 IServiceManager입니다.
 14     sp<IServiceManager> sm = defaultServiceManager();   //이순간 서비스 매니저를 만들고..
    

         // myserver1을 핸들을 알아냅니다.
         // 핸들(번호)를 알아낸 후 해당 번호를 관리하는 BpBinder객체를 만들어 줍니다.
         // BpBinder는 내부적으로 transact()함수가 있는데
         // 이 함수가 IPCThreadState를 사용해서 ioctl()함수로 드라이버와 통신합니다.
 16     sp<IBinder> svc = sm->getService(String16("myserver1")); // 결국 내부적으로 뭘할까요?
 17
 18     // now call the server func
 19     Parcel data, reply;
 20
 21     data.writeInt32(3);
 22     data.writeInt32(5);
 23     svc->transact(SUB, data, &reply);
 24     printf("result : %d\n", reply.readInt32());
 25     return 0;
 26

==============================================================
2번째꺼는 transact로 Add, Sub를 호출한다. Add, Sub를 호출하는 것처럼 보이지 않고
client를 만드는 사람은 SUB, ADD라는 코드를 이용해서 실행하는 모양새임

그래서 3번재꺼는 Add, Sub라는 걸 마치 server에서 사용하는 것처럼 할것임
이걸 프락시라고 말하는 것임

다른 서버의 함수를 호출하도록 만듬 Remote Process Call(RPC)를 짠 것임
 

//myclient2.cpp
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>

using namespace android;

 
enum {
    ADD = IBinder::FIRST_CALL_TRANSACTION,
    SUB,
};

class BpCalc : public RefBase
{
    sp<IBinder> mRemote;
public:
    BpCalc(sp<IBinder>& p) : mRemote(p) {}
    sp<IBinder> remote() const {return mRemote; }

    int Add(int a, int b) {
        Parcel data, reply;
        data.writeInt32(a);
        data.writeInt32(b);
        int ret = mRemote->transact(ADD, data, &reply);
        return reply.readInt32();
    }
    int Sub(int a, int b) {
        Parcel data, reply;
        data.writeInt32(a);
        data.writeInt32(b);
        int ret = mRemote->transact(SUB, data, &reply);
        return reply.readInt32();
    }

    //모든 Proxy안에는 바인더를 인자로 받아서 객체를 만드는 static멤버를 만들기로 약속하자.
    static sp<BpCalc> asInterface(const sp<IBinder>& binder)
    {
         return new BpCalc(binder);
    }
};


template<typename T> sp<T> my_interface_cast(const sp<IBinder>& binder)
{
    return T::asInterface(binder);  //binder를 가지고 proxy를 얻을 수 있음
    //return new T(binder); // If Constructor is private? No way~
}


int main()
{
    sp<ProcessState> proc( ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> svc = sm->getService(String16("myserver1"));

    //바인더를 객체로 변경하는 코드입니다.
    //sp<BpCalc> pCalc = new BpCalc(svc);

    //숙제는 : 바인더로부터 Proxy객체를 만드는 캐스팅
    sp<BpCalc> pCalc = my_interface_cast<BpCalc>(svc);
    //윗 코드 binder를 proxy로 캐스팅하는 것처럼 보이지만 실제로는 객체를 생성한 것임

    int ret = pCalc->Add(1,2);
    printf("result : %d\n", ret);

    return 0;
}

반응형
반응형

VI에서 소스 분석에 유용한 ctags
http://rucifer.tistory.com/entry/소스-분석에-유용한-ctags


VI테크닉 정리(화면분할, mark)
http://blog.dasomoli.org/89
반응형
반응형
// intro1day.cpp : Defines the entry point for the console application.
//

//#include "stdafx.h"


#include <iostream>
using namespace std;

#if 0

//int_cast만드는 연습(interface cast와 비슷, 최상위 class에는 pure virtual 함수로 작성해서 
//하위 class에서 강제로 toInt를 만들게 한다면 interface_cast가 될 것
class Test
{
public:
//Test 클래스는 int값을 하나 꺼낼 수 있다고 가정해 봅시다.
static int toInt() {return 10;}
};

template<typename T> int int_cast(T obj)
{
return T::toInt();
}

int main()
{
//int n = Test::toInt();
Test t;
int n = int_cast<Test>(t);
printf("%d",n);
}
#endif

#if 0
//1. 함수템플릿
//    - T가 결정되어서 함수가 되는 과정을 인스턴스화 라고 한다.
//      암시적/명시적 인스턴스화가 있다.
template<typename T> T Max(T a, T b)
{
return a < b ? b: a;
}

int main()
{
cout << Max(1,3) << endl; // int Max(int, int) 버전의 함수를 생성
cout << Max(3.4, 2.1) << endl; // doudle Max(double, double) 버전의 함수를 생성

cout << Max<int> (65, 'B') << endl; //함수템플릿의 T를 명시적으로 지정하는 방법.

return 0;
}
#endif

#if 0
//클래스 템플릿..!!
template<typename T> class complex
{
T real;
T image;
publid:
complex(T a = 0, T b = 0): real(a), image(b) {}

//복사생성자
//U가 T로 변환된다면 complex<U>도complex<T>로 변환되어야 한다. - template복사생성자 필요
template<typename U> complex( const complex<U>&c )
{
real = c.real;
image = c.image;
}

template<typename U> friend class complex;
};



itn main()
{
complex<int> c1(1,2);
complex<int> c2 = c1;

complex<double> c3 = c1; //뭘까요? ..
}
#endif

#if 0 // 이거 앞으로 잘 활용할 수 있을 것 같은데 dkim
//Mix in template - 안드로이드에서 자주 사용하는 기법.
template<typename T>
class A
{
public:
void foo() { static_cast<T*>(this)->goo();} //T는 내 자식일것임 자기 자신(this)를 자기 자식으로 casting함 결국 자식께 부르게 됨
void goo() {cout << "A::goo" << endl;} //1 가상함수는 자식이 재정의하면 자식꺼를 부르게 해주자
//가상함수를 너무 많이 쓰면 성능 저하의 원인이다 그래서 가상함수 빼고 해 보겠음
// template를 이용해서 가상함수를 사용해야 할 것을 해결함 속도 증가

};

//부모가 template이고 그 템플릿이자로 현재 클래스의 이름을 보내는 기술..
// Mix in Template이라고 부른다. 여러가지 활용이 가능한데.. 아래의 경우는 비가상함수를
// 가상함수 처럼 동작하게 하는 기술이다.
class B :public A<B>
{
public:
void goo() { cout << "B::goo" << endl;} //2
};

int main()
{
B b;
b.foo(); // 1? 2?
}
#endif

#if 0 // wow~ dkim
// Mix in template 2 - 안드로이드에서 자주 사용하는 기법.
template<typename T> 
class A
{
protected:
~A() {cout << "~A()" << endl;}
void foo() {cout << "A::foo" << endl;}

public:
void clean()
{
delete static_cast<T*>(this);
}
};

class B: public A<B>
{
public:
~B() {cout << "~B()" << endl;}
virtual void foo() {cout << "B::foo" << endl;}

};

int main()
{
A<B>* p = new B; 
//virtual이 없는 foo라면부모 객체로 자식instance를 가리킬 때는 C++에서는 foo부르면 부모께 불림(메모리 안보고 타입만봄(정적언어 complile time)
//실행할 때 메모리를 보고 결정하라고 하는게 virtual이라는 keyword임
//그래서 foo에 virtual을 붙이면 자식꺼 부름

//p->foo();
//delete p; //이건? 소멸자가 항상 virtual이어야 하는 이유임
//그런데 virtual은 느리니까 virtual 빼고 protected로 만들면?
//부모 소멸자가 protected니까 error가 나는데 
// 이제 B의 소멸자를 호출하기 위해 꼭 캐스팅해서 사용하자. 불편하지만 제대로 호출된다.!
//delete static_cast<B*>(p); //이렇게 하니까 잘 되긴 하지만 불편하다.
//그래서 clean을 만들어보자
p->clean(); //가상함수 테이블이 없어진 가벼운 객체가 만들어졌으므로 이제 쉽게 쓰자
}
#endif

#if 0 
//상속과 upcasting(부모포인터로 자식 객체를 담을 수 있다)
// * 이런 장점을 활용하여 동종을 저장하는 컬렉션을 만들 수 있다.
//      그리고 동종(동일부모자식)을 처리하는 함수를 만들 수 잇다.
// * 모든 자식의 공통의 특징은 부모에 있어야 한다.
// * 
#include <vector> //STL vector .. 안드로이드에서도 있습니다.
//도형 편집기를 만들어 보자. - 아주 많은 개념이 등장합니다 꼭 알아두세요..
// 1. 각 도형의 특징을 관리하는 타입을 만들어보자
// 2. 동일 부모가 있다면 모든 도형을 묶을 수 있지 않을까???
// 3. 모든 자식은 공통의 기능은 반드시 부모로 부터 제공되어야 한다.
// 4. 자식이 재정의 하게 되는 함수는 반드시 가상함수로 하자.
// 5. OCP 이론 
//    다형성이 좋은 점은 나중에 기능(class)가 추가되어도 이 code는 수정할 필요가 없음
//    객체지향의 원칙 중 OCP : Open Close Principle : 기능 추가에 열려 있고(open), 코드 수정에 닫혀(Close)있어야 한다는 이론(Principle)
// 6. 
class Shape
{
public:
// template method : 변하지 않는 전체적인 알고리즘은 부모가 public 비 가상함수로 만들고
//                   변해야 하는 세부 알고리즘은 자식이 prottected가상함수로 재정의 하도록 하는 디자인
void Draw() //자식에게 재정의하지 못하게 하면 좋겠지만 C++은 그런 기능은 없고, 최소한 virtual은 빼자
{
//Mutex.Lock();
OnDraw();
//Mutex.Unlock();
}
public:
virtual void OnDraw() = 0; //pure virtual func.. 자식이 반드시 만들어야함(강제)
                          //이런 디자인 기법을 template Method라고 부른다.

};


class Rect : public Shape
{
protected :
virtual void OnDraw() {cout << "Rect::Draw" << endl;}
};
class Circle : public Shape
{
protected: //RealDraw를 직접 부르면 Mutex를 못쓰니까 못쓰게 막자(private는 자기네들끼리도 못하게 하니까 protected로)
virtual void RealDraw() {cout << "Circle::Draw" << endl;}
};


int main()
{
vector<Shape*> v;
while(1)
{
int cmd;
cin >> cmd;
if(cmd==1) v.push_back(new Rect);
else if (cmd == 2) v.push_back(new Circle);
else if(cmd == 9)
{
for(int i = 0; i < v.size(); i++)
v[i]->Draw(); //다형성 , 동일 함수 호출 표현식이 상황에 따라 다른 함수를 호출함

}
}
}

#endif

#if 0
#include "List.h" /// froyo/framework/base/include/utils에 sp, RefBase, list, vector등이 있습니다.
using namespace android; //안드로이드의 모든 클래스는 이 안에 있습니다.

// 요즘 C++의 콜렉션 클래스(뭔가를 저장하는 클래스)를 이해하려면 반복자를 알아야 합니다.

int main()
{
List<int> st;

st.push_back(10);
st.push_back(20);
st.push_back(30);
st.push_front(40);

st.insert(++st.begin(), 100);
List<int>::iterator p = st.begin(); // p는 st의 처음을 가리키는 포인터 역할을 함
List<int>::iterator p1 = st.end(); //st의 마지막을 가리키는 포인터

while(p != st.end())
{
cout << *p << endl;
++p;
}


//마지막 요소 제거하기
st.erase(--p1); //st의 마지막을 가리키는 포인터
p = st.begin();
//while(p != st.end())
//{
// cout << *p << endl;
// ++p;
//}
}
#endif

//1. 부분전문화 개념

/*
//primary template
template<typename T> class Stack
{

};

//부분 전문화
template<typename T> class Stack<T*>
{

};

//전문화 버전
template<typename T> class Stack<char*>
{

};

int main()
{
Stack<int> s1;
Stack<int*> s2;
Stack<char*> s3;
}
*/


//안드로이드가 사용하는 가장 복잡한 template기술 - traits 기술
// traits란? T가 pointer인지 아닌지, 구조체인지 아닌지 공용체인지 아닌지를 알아내는 기술
/*
template<typename T> T Max(T a, T b)
{
if(T is Pointer)
return *a < *b ? b : a;
return a < b ? b : a ;
};

int main()
{
int x = 10, y = 20;

Max(x,y);
Max(&x, &y);
}
*/

//T가 포인터인지 알아내는 기술(한마디로 컴파일러에게 물어본거)
// framework/base/include/utils/typehelpers.h

// primary template 은 FALSE리턴
template<typename T> struct trait_pointer
{
enum{value = false};
};
//부분전문화 버전은 TRUE 리턴
template<typename T> struct trait_pointer<T*>
{
enum{value = true};
};
// primary template 은 FALSE리턴
template<typename T> struct trait_array
{
enum{size = 0};
enum{value = false};
};
//부분전문화 버전은 TRUE 리턴
template<typename T, int N> struct trait_array<T[N]>
{
enum{size = N};
enum{value = true};
};
template<typename T> void foo(const T& a)
{
if(trait_array<T>::value) 
cout << "Array, " << "Size is " << trait_array<T>::size << endl;
else
cout << "not Array" << endl;

if(trait_pointer<T>::value)
cout << "Pointer" << endl;
else
cout << "not Pointer" << endl;
};

int main()
int n[] = {0,1,2};
foo(n);
}



=============================
Default 생성자 관련


class Animal
{
public:
Animal() {cout << "Animal Ctor" << endl;}
Animal(char * sz) {cout << "Animal Ctor(char)" << endl;}

};

class Dog : public Animal
{
public:
Dog() : Animal() {cout << "Dog Ctor" << endl;}
Dog(char * sz) : Animal(sz) {cout << "Dog Ctor(char)" << endl;} //Default 생성자를 이해해야 함
};

int main()
{
Animal a;
Animal a2("aa");
cout << "---------------" << endl;
Dog d1;
Dog d2("aaa");
}

 =========================================
#if 0
template<typename T> class Stack
{
public:
//다음 중 생성자로 맞는 것은?
Stack() { cout << "Stack" << endl;}   // ok...
//Stack<T>() {}                       // error

//복사생성자
Stack(const Stack& s) {} // 함수인자로는 2번이 정확한 표현이지만 이 표현도 허용
Stack(const Stack<T>& s) {} //ok

//클래스 템플릿의 멤버 함수를 외부 구현
void push(const T* a);

// 클래스 템플릿의 멤버 함수 템플릿.. 
// 예)complex만들기 complex<double> = complex<int>가 되게 하기 위해 복사생성자를 아래처럼 구현했었음
template<typename U> T foo(U a);
};

//복사생성자와 대입연산자 만들때만 이런식으로 하게 된다.  android에서는 sp에서 복사, 대입에 나옴
template<typename T> template<typename U> T Stack<T>::foo(U a)
{

}

//둘 중 어느게 맞는건가요?
template<typename T> void Stack::push(const T& a)        // error
template<typename T> void Stack<T>::push(const T& a)     // ok
{

}
#endif


=====================================================
#if 0
//템플릿 인자의 3가지 종류 
template<typename T> class List
{

};

template<typename T, int N> class Stack1
{
T buff[N];
};

template<template<typename> class C, typename T> class Stack2
{
C c; // error
c<T> c; // ok

};

int main()
{
List ss; // List는 템플릿이다
List<int> s; //List는 타입이다.
Stack1<int, 10> s2;    
Stack2<List, int> s3;


==> template인자로 들어갈 수 있는 것은 3가지 ==> 타입, 정수, 템플릿
}
#endif

================================================================ 
  
//template을 사용해서 부모가 바귀게 하는 기술.. BpInterface/BnInterface가 사용하는 기술
template<typename T, typename ThreadModel> class List : public ThreadModelList
{
public:
void push(const T&a )
{
Lock();
...
Unlock();
}
};

class MultiThread
{
public:
void Lock() {mutex.lock();}
void UnLock() {mutex.Unlock();}
};

class SingleThread
{
public:
void Lock(){}
void UnLock() {}
};
// 사용한는 방법 ------------------------
// 부모를 가져다 쓰는 순간에 결정함
List<int, MultiThread> st;
List<int, SingleThread> st; //어짜피 최적화되면 성능저하 없음

 ================================================================  




 
반응형
반응형
윈도우 7에서 새폴더를 만든 후
이름을 GodMode.{ED7BA470-8E54-465E-825C-99712043E01C} 
으로 변경하면 엄청난 Tweak 메뉴들이 ㄷㄷㄷ

반응형

+ Recent posts