2012-02-27 38 views

Trả lời

25

Vì NDK r8d, điều này có thể được giải quyết một cách đơn giản hơn nhiều.

  1. Tạo một dự án với hệ thống phân cấp thư mục sau:

    project/ 
        jni/ 
         Android.mk 
         Application.mk 
         *.c, *.cpp, *.h, etc. 
    
  2. Fill trong Android.mk với các nội dung sau đây. Điều quan trọng nhất là dòng cuối cùng.Kiểm tra tài liệu NDK để biết ý nghĩa của các biến khác.

    LOCAL_PATH := $(call my-dir) 
    
    include $(CLEAR_VARS) 
    
    LOCAL_MODULE := name-of-your-executable 
    LOCAL_SRC_FILES := a.cpp b.cpp c.cpp etc.cpp 
    LOCAL_CPPFLAGS := -std=gnu++0x -Wall -fPIE   # whatever g++ flags you like 
    LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -fPIE -pie # whatever ld flags you like 
    
    include $(BUILD_EXECUTABLE) # <-- Use this to build an executable. 
    
  3. Vào thư mục project/, và chỉ cần gõ

    ndk-build 
    

    Kết quả sẽ được đặt trong project/libs/<arch>/name-of-your-executable.

+5

Để chạy chương trình trên thiết bị của bạn: (giả sử bạn có 'adb' trên đường dẫn của bạn và thiết bị của bạn là thiết bị được hiển thị bởi 'thiết bị adb' và là thiết bị cánh tay và tên có thể thực thi là mypgm): ' adb push libs/armeabi/mypgm/data/tmp/mypgm 'then' adb shell chmod 777/dữ liệu/tmp/mypgm 'và chạy nó' adb shell/data/tmp/mypgm '. Đặt nó vào nơi bạn muốn - Tôi đã sử dụng/data/tmp trong ví dụ này. –

+0

Ứng dụng của tôi có thể lấy đối số dòng lệnh không, ví dụ: nếu ứng dụng của tôi nhận tên tệp và vị trí tệp dưới dạng đối số dòng lệnh. Ngoài ra các biến môi trường như LD_LIBRARY_PATH hoạt động trong Android. Get_env() có hoạt động không? – kanna

+0

@kanna: (1) Sử dụng phương thức 'chính (argc, argv)' thông thường. (2) Bạn có thể thử. Mặc dù nó là 'getenv()'. – kennytm

20

http://www.bekatul.info/content/native-c-application-android [vỡ (9 tháng 11 năm 2015)]

Để tóm tắt bài báo ...

Các mã kiểm tra là:

#include <stdio.h>//for printf 
#include <stdlib.h>//for exit 

int main(int argc, char **argv) 
{ 
     int i = 1; 
     i+=2; 

     printf("Hello, world (i=%d)!\n", i); 

     return 0; 
     exit(0); 
} 

Các Makefile là:

APP := test 
ROOT := /home/dd/android 
INSTALL_DIR := /data/tmp 
NDK_PLATFORM_VER := 8 

ANDROID_NDK_ROOT := $(ROOT)/android-ndk-r5 
ANDROID_NDK_HOST := linux-x86 
ANDROID_SDK_ROOT := $(ROOT)/android-sdk-linux_86 
PREBUILD := $(ANDROID_NDK_ROOT)/toolchains/arm-eabi-4.4.0/prebuilt/$(ANDROID_NDK_HOST) 

BIN := $(PREBUILD)/bin/ 
LIB := $(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib 
INCLUDE := $(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include 

CC := $(BIN)/arm-eabi-gcc 
GDB_CLIENT := $(BIN)/arm-eabi-gdb 

LIBCRT := $(LIB)/crtbegin_dynamic.o 

LINKER := /system/bin/linker 

DEBUG := -g 

CFLAGS := $(DEBUG) -fno-short-enums -I$(INCLUDE) 
CFLAGS += -Wl,-rpath-link=$(LIB),-dynamic-linker=$(LINKER) -L$(LIB) 
CFLAGS += -nostdlib -lc 

all: $(APP) 

$(APP): $(APP).c 
     $(CC) -o [email protected] $< $(CFLAGS) $(LIBCRT) 

install: $(APP) 
     $(ANDROID_SDK_ROOT)/platform-tools/adb push $(APP) $(INSTALL_DIR)/$(APP) 
     $(ANDROID_SDK_ROOT)/platform-tools/adb shell chmod 777 $(INSTALL_DIR)/$(APP) 

shell: 
     $(ANDROID_SDK_ROOT)/platform-tools/adb shell 

run: 
     $(ANDROID_SDK_ROOT)/platform-tools/adb shell $(INSTALL_DIR)/$(APP) 

debug-install: 
     $(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILD)/../gdbserver $(INSTALL_DIR)/gdbserver 
     $(ANDROID_SDK_ROOT)/platform-tools/adb shell chmod 777 $(INSTALL_DIR)/gdbserver 

debug-go: 
     $(ANDROID_SDK_ROOT)/platform-tools/adb forward tcp:1234: tcp:1234 
     $(ANDROID_SDK_ROOT)/platform-tools/adb shell $(INSTALL_DIR)/gdbserver :1234 $(INSTALL_DIR)/$(APP) 

debug: 
     $(GDB_CLIENT) $(APP) 

clean: 
     @rm -f $(APP).o $(APP) 

Tác giả lưu trữ các tập tin trên/máy tính Linux địa phương cô của mình tại địa chỉ:

/home/dd/android/dev/native/test.c 
/home/dd/android/dev/native/Makefile 

Tác giả sau đó biên soạn và thử nghiệm nó với:

[email protected]:~/android/dev/native$ make clean; make; make install; make run 
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-gcc -c -fno-short-enums -I/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/include test.c -o test.o 
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-g++ -Wl,--entry=main,-dynamic-linker=/system/bin/linker,-rpath-link=/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/lib -L/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/lib -nostdlib -lc -o test test.o 
/home/dd/android/android-sdk-linux_86/platform-tools/adb push test /data/tmp/test 
45 KB/s (2545 bytes in 0.054s) 
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell chmod 777 /data/tmp/test 
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell /data/tmp/test 
Hello, world (i=3)! 

SDK và NDK sử dụng là:

source code: /home/dd/android/dev/native 
android ndk: /home/dd/android/android-ndk-r5 
android sdk: /home/dd/android/android-sdk-linux_86 

Tuy nhiên, hướng dẫn gỡ lỗi là phần thực sự tốt! Sao chép và dán ...

Đặt biên dịch cho phép gỡ lỗi:

DEBUG = -g 
CFLAGS := $(DEBUG) -fno-short-enums -I$(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include 

copy file gdbserver ($ (prebuild) /../ gdbserver) để giả lập, thêm mục tiêu trong Makefile hơn để làm cho nó dễ dàng:

debug-install: 
     $(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILD)/../gdbserver $(INSTALL_DIR)/gdbserver 
     $(ANDROID_SDK_ROOT)/platform-tools/adb shell chmod 777 $(INSTALL_DIR)/gdbserver 

Bây giờ chúng tôi sẽ gỡ lỗi nó @ cổng 1234:

debug-go: 
     $(ANDROID_SDK_ROOT)/platform-tools/adb forward tcp:1234: tcp:1234 
     $(ANDROID_SDK_ROOT)/platform-tools/adb shell $(INSTALL_DIR)/gdbserver :1234 $(INSTALL_DIR)/$(APP) 

Sau đó, thực hiện nó:

[email protected]:~/android/dev/native$ make clean; make; make install; make debug-install; make debug-go 
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-gcc -c -g -fno-short-enums -I/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/include test.c -o test.o 
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-g++ -Wl,--entry=main,-dynamic-linker=/system/bin/linker,-rpath-link=/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/lib -L/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/lib -nostdlib -lc -o test test.o 
/home/dd/android/android-sdk-linux_86/platform-tools/adb push test /data/tmp/test 
71 KB/s (3761 bytes in 0.051s) 
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell chmod 777 /data/tmp/test 
/home/dd/android/android-sdk-linux_86/platform-tools/adb push /home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/../gdbserver /data/tmp/gdbserver 
895 KB/s (118600 bytes in 0.129s) 
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell chmod 777 /data/tmp/gdbserver 
/home/dd/android/android-sdk-linux_86/platform-tools/adb forward tcp:1234: tcp:1234 
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell /data/tmp/gdbserver :1234 /data/tmp/test 
Process /data/tmp/test created; pid = 472 
Listening on port 1234 

Bây giờ mở console khác và thực hiện các chương trình gỡ rối:

[email protected]:~/android/dev/native$ make debug 
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-gdb test 
GNU gdb 6.6 
Copyright (C) 2006 Free Software Foundation, Inc. 
GDB is free software, covered by the GNU General Public License, and you are 
welcome to change it and/or distribute copies of it under certain conditions. 
Type "show copying" to see the conditions. 
There is absolutely no warranty for GDB. Type "show warranty" for details. 
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-elf-linux"... 
(gdb) target remote :1234 
Remote debugging using :1234 
warning: Unable to find dynamic linker breakpoint function. 
GDB will be unable to debug shared library initializers 
and track explicitly loaded dynamic code. 
0xb0001000 in ??() 
(gdb) b main 
Breakpoint 1 at 0x82fc: file test.c, line 6. 
(gdb) c 
Continuing. 
Error while mapping shared library sections: 
/system/bin/linker: No such file or directory. 
Error while mapping shared library sections: 
libc.so: Success. 

Breakpoint 1, main (argc=33512, argv=0x0) at test.c:6 
6    int i = 1; 
(gdb) n 
7    i+=2; 
(gdb) p i 
$1 = 1 
(gdb) n 
9    printf("Hello, world (i=%d)!\n", i); 
(gdb) p i 
$2 = 3 
(gdb) c 
Continuing. 

Program exited normally. 
(gdb) quit 

Vâng nó là ok. Và giao diện điều khiển khác sẽ cung cấp thêm đầu ra như vậy:

Remote debugging from host 127.0.0.1 
gdb: Unable to get location for thread creation breakpoint: requested event is not supported 
Hello, world (i=3)! 

Child exited with retcode = 0 

Child exited with status 0 
GDBserver exiting 
+0

Dường như trang web đã sao lưu - đó là một bài viết khá lớn, đó là lý do tại sao tôi không lặp lại ở đây. –

3

Vì tôi không có 50 danh tiếng nên tôi không thể nhận xét về câu trả lời của ai đó ở đâu đó, vì vậy tôi làm câu trả lời ở đây.

Tôi xin trích dẫn một lỗi/misprecision: như xa như gdbserver là có liên quan, các lệnh adb

$(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILD)/../gdbserver $(INSTALL_DIR)/gdbserver 

sẽ không bao giờ có thể làm việc, vì lý do hiển nhiên, bởi vì "giữa" thư mục $ (prebuild) và gdbserver, có thư mục android-arm. Nó là tốt hơn để thiết lập

PREBUILDDEBUG=$(ANDROID_NDK_ROOT)/prebuilt/android-arm 

và để thay thế cho lệnh cựu bởi

$(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILDDEBUG)/gdbserver $(INSTALL_DIR)/gdbserver 

Với tất cả mọi thứ này làm việc cho tôi với một thiết bị ảo Android. (Không có lỗi phân đoạn rõ ràng.) Trên thiết bị thực của tôi, tôi có lỗi phân đoạn. Đó là

make run 

một phần. tôn trọng để gỡ lỗi một phần với, có thể là trên giả lập hoặc trên thiết bị thật, tôi luôn luôn có được một "không thể truy cập vào bộ nhớ" khi tôi làm

b main 

trong chế độ gdb ... Bất kỳ ý tưởng? Trợ giúp sẽ được đánh giá cao.

+0

A -entry = chính trong CFLAGS cho phép tôi tránh có lỗi phân đoạn, btw. –

+0

cảm ơn phản hồi của bạn. Chủ đề này khá phức tạp nên mỗi bit thông tin hữu ích đều có giá trị. –

+0

Đừng ngần ngại upvote! –

4

Đây là một dự án ví dụ tuân theo câu trả lời của KennyTM. Bạn có thể tạo nó từ đầu hoặc sửa đổi một dự án khác, ví dụ: hello-jni trong các mẫu NDK.

JNI/main.c:

#include <stdio.h> 
int main() { 
    printf("hello\n"); 
    return 0; 
} 

JNI/Application.mk:

#APP_ABI := all 
APP_ABI := armeabi-v7a 

JNI/Android.mk:

LOCAL_PATH := $(call my-dir) 

# first target: the hello-jni example 
# it shows how to build multiple targets 
# {{ you may comment it out 
include $(CLEAR_VARS) 

LOCAL_MODULE := hello-jni 
LOCAL_SRC_FILES := hello-jni.c 
LOCAL_LDLIBS := -llog -L$(LOCAL_PATH)/lib -lmystuff # link to libmystuff.so 

include $(BUILD_SHARED_LIBRARY) 
#}} you may comment it out 


# second target 
include $(CLEAR_VARS) 

LOCAL_MODULE := hello 
LOCAL_SRC_FILES := main.c 

include $(BUILD_EXECUTABLE) # <-- Use this to build an executable. 

tôi h ave cần lưu ý rằng bạn sẽ không thấy bất kỳ đăng nhập nào trong đầu ra stdout, bạn sẽ phải sử dụng adb logcat để xem nó.

Vì vậy, nếu bạn muốn đăng nhập:

JNI/main.c:

#include <stdio.h> 
#include <android/log.h> 
int main() { 
    printf("hello\n"); 
    __android_log_print(ANDROID_LOG_DEBUG , "~~~~~~", "log %i", 0); // the 3rd arg is a printf-style format string 
    return 0; 
} 

và phần tương ứng trong JNI/Android.mk trở thành:

LOCAL_PATH := $(call my-dir) 

#... 

include $(CLEAR_VARS) 

LOCAL_MODULE := hello 
LOCAL_SRC_FILES := main.c 
LOCAL_LDLIBS := -llog # no need to specify path for liblog.so 

include $(BUILD_EXECUTABLE) # <-- Use this to build an executable. 
Các vấn đề liên quan