반응형
NDK작업 순서

1. eclipse 에서 android 프로젝트 생성 후에 native함수를 사용하는 소스 작업..

2. 프로젝트 최상위 디렉토리에서 javah를 사용해서  native function의 헤더 파일 생성..

    javah -classpath bin org.example.myNDK2.MyNDK2Activity

3. 프로젝트 디렉토리 하위 디렉토리로 jni폴더 생성 후에 2에서 생성한 헤더 복사해 오기

4. c 소스 구현 ==> binder client가 실행이 될거고 server의 function이 호출되고 

5. Android.mk파일 만든 후에.. ndk-build명령으로 빌드

6. 실행.. 
반응형
반응형
./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_

반응형

+ Recent posts