많이 쓰시는 분들은 무슨 의미인지 바로 파악이 가능하실 텐데 make를 하되 4개의 스레드를 만들어서 돌린다는 의미입니다. 여기서 -j4를 파라미터라고 합니다. 그런데 C프로그램에선 이것을 어떻게 파악을 할까요?
C/C++의 기본적인 main함수의 구조를 보면
int main(int argc, char[][] argv)
이런 구조가 있습니다.
(int 대신 void를 쓰기도 하지만 어찌됐든 보통은 int가 기본입니다.)
여기서는 argc라는 정수형 하나와 argv라는 이중 배열 문자 혹은 문자열의 배열을 의미합니다.
그 어떤 파라미터를 받지 않는 다면 뒷부분을 모두 생략 가능합니다만 CLI특성상 뒤에 파라미터를 받는 경우가 대부분입니다.
즉, argc는 파라미터의 갯수이고 argv는 파라미터의 갯수입니다.
다만 argv[0]에 들어가는 것은 무조건 실행되는 프로그램의 경로를 넣습니다.
그러니까
make -j4
이 명령을 넣었을 때 make의 main함수에서는
argc = 2
argv[0] = /bin/make
argv[1] = -j4
이렇식으로 들어간다는 의미입니다. 그러면 다시한번 vlmcsd의 함수를 뜯어볼까요. (이것이 본래 main함수라는건 잊지 않으셨죠?)
int argc와 함께 CARGV argv 변수를 받고 있습니다. CARGV는 define된 무언가일겁니다. (VSCode에서 저건 보통 define 된 이름입니다.) CARGV를 한번 검색해봅시다.
types.h에 보면 typedef로 처리되어 있군요. 구조체가 아니었네요. const char *const * 형태를 의미합니다. 즉, 이중포인터 = 이중배열 구조를 의미합니다.
argv구조와 같다는 것입니다.
이걸 말씀드리는 이유는 server_main함수를 안드로이드의 자바/코틀린에서 호출할 예정이기 때문입니다. 그러려면 함수의 구조를 그대로 만들어서 호출해야겠지요.
그리고 vlmcsd의 동작에 대해 말할 필요가 있습니다.
터미널에서 vlmcsd를 실행하면
그냥 이렇게 커서가 뚝 떨어집니다. 그래서 ps -A | grep vlmcsd를 해보면
이렇게 뒤에서 프로세스가 돌고 있는 것을 볼 수 있습니다.
이건 백그라운드에서 돌릴 수 있게끔 코드가 짜여져 있기 때문입니다. 그런데 우리는 vlmcsd를 따로 실행하는 것이 아니라 안드로이드 앱의 프로세스 내에서 이것을 돌려야 합니다. 미리 말씀드리자면 이 코드를 그대로 호출한 결과 안드로이드 프로세스가 같이 죽어버리는 결과가 나옵니다. 백그라운드 프로세스에 등록후에 자기 자신을 꺼버리게 때문입니다.
그래서 다른 서버프로그램 처럼 대몬으로 동작하는 것이 아니라 대기하게 하는 방식이 필요합니다. 그런데 코드를 뒤져보니 foreground에서 돌아가게 하는 코드가 존재하더군요.
사실 ./vlmcsd -h 만 해도 뜨는 파라미터입니다.
그러니까 ./vlmcsd -D 이렇게 명령을 주면
이렇게 커서가 떨어지지 않고 대기를 하게 됩니다.
이 이야기를 하는 이유는 눈치빠른 분이라면 아실거 같은데 server_main함수를 호출 할때 argv에 "-D"를 넣어야 한다는 겁니다.
그러니까 함수 호출 형태가
int argc = 2;
char[][] argv = {"./', "-D"};
server_main(argc, argv);
이렇게 되어야 한다는 겁니다. argc가 2인 이유는 1번째는 무조건 경로가 들어가야 하므로 추가 파라미터가 2번째부터 들어가야 하기 때문입니다. 아래 argv 보면 첫번째 배열에는 "./"가 들어가 있지요. 그냥 무엇이 들어가야 할지 몰라서 현위치를 지정했습니다.
재미없는 이론 시간은 이제 끝났습니다. 이제 진짜로 Android Studio에서 이 코드를 넣어봅시다. Android Studio의 세팅은 생략하겠습니다.
Android Studio에서 New Project를 해봅시다.
여기서 Native C++을 사용하겠습니다.
그리고 저는 낡은 인간(?)이므로 JAVA를 사용할 예정입니다. Kotlin이 익숙하신 분은 Kotlin을 쓰시면 됩니다.
그리고 컴파일러는 그냥 기본 툴체인을 사용합니다. 어차피 저희는 표준C를 사용하는 것이니 그냥 편한대로 하면 됩니다.
`
이제 기본적인 구조가 완성 되었습니다. 이 기본 구조도 분석해볼 필요는 있는데 굳이 따로 하지는 않겠습니다. 간단하게 C++에서 문자열을 리턴하는 함수를 native-lib.cpp에 만들고 MainActivity에서 native로 해당 함수(stringFromJNI() )를 선언한뒤 onCreate할때 해당 함수를 호출하는 방식입니다.