zoukankan      html  css  js  c++  java
  • 两种方法将Android NDK samples中helloneon改成C++

    一、第一种方法:
    1.修改helloneon.c 中代码
     a.将
      char*  str;
       改为
         char str[512] = {0};
     b.将
      asprintf(&str, "FIR Filter benchmark:\nC version          : %g ms\n", time_c);
       改为
         sprintf(str, "FIR Filter benchmark:\nC version    : %g ms\n", time_c);
       同时删除 free(str);
       (b 项 有两处都要修改)
     c.将
      return (*env)->NewStringUTF(env, buffer);
     改为
      return env->NewStringUTF(buffer);
    2.将helloneon.c改名为helloneon.cpp
      将helloneon-intrinsics.c改名为helloneon-intrinsics.cpp
    3.将Android.mk中
     将
      LOCAL_SRC_FILES := helloneon.c
     改为
      LOCAL_SRC_FILES := helloneon.cpp

     将
      LOCAL_SRC_FILES += helloneon-intrinsics.c.neon
     改为
      LOCAL_SRC_FILES += helloneon-intrinsics.cpp.neon
    4.打开 helloneon.cpp
      在#include 和 各种 #define 后面添加:
     #ifdef __cplusplus
     extern "C" {
     #endif
      在代码段最后面添加:
       #ifdef __cplusplus
     }
     #endif
      不修改这一条的话,会提示找不到stringFromJNI。

    不明问题:
    1.经常提示一些jni和cpu-features的函数未定义。在路径中添加jni.h和cpu-features.h
    2.即便是添加了arm_neon.h,还是会提示:
    Type 'int16x4_t' could not be resolved helloneon-intrinsics.cpp /HelloNeon/jni line 35
    但是 重启eclipse 一般就不提示了。一旦打开了helloneon-intrinsics.cpp还是会提示。

    最终 hello-neon.cpp

      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  */
     17 #include <jni.h>
     18 #include <time.h>
     19 #include <stdio.h>
     20 #include <stdlib.h>
     21 #include <cpu-features.h>
     22 #include "helloneon-intrinsics.h"
     23 
     24 #define DEBUG 0
     25 
     26 #if DEBUG
     27 #include <android/log.h>
     28 #  define  D(x...)  __android_log_print(ANDROID_LOG_INFO,"helloneon",x)
     29 #else
     30 #  define  D(...)  do {} while (0)
     31 #endif
     32 
     33 #ifdef __cplusplus
     34 extern "C" {
     35 #endif
     36 
     37 /* return current time in milliseconds */
     38 static double
     39 now_ms(void)
     40 {
     41     struct timespec res;
     42     clock_gettime(CLOCK_REALTIME, &res);
     43     return 1000.0*res.tv_sec + (double)res.tv_nsec/1e6;
     44 }
     45 
     46 
     47 /* this is a FIR filter implemented in C */
     48 static void
     49 fir_filter_c(short *output, const short* input, const short* kernel, int width, int kernelSize)
     50 {
     51     int  offset = -kernelSize/2;
     52     int  nn;
     53     for (nn = 0; nn < width; nn++) {
     54         int sum = 0;
     55         int mm;
     56         for (mm = 0; mm < kernelSize; mm++) {
     57             sum += kernel[mm]*input[nn+offset+mm];
     58         }
     59         output[nn] = (short)((sum + 0x8000) >> 16);
     60     }
     61 }
     62 
     63 #define  FIR_KERNEL_SIZE   32
     64 #define  FIR_OUTPUT_SIZE   2560
     65 #define  FIR_INPUT_SIZE    (FIR_OUTPUT_SIZE + FIR_KERNEL_SIZE)
     66 #define  FIR_ITERATIONS    600
     67 
     68 static const short  fir_kernel[FIR_KERNEL_SIZE] = {
     69     0x10, 0x20, 0x40, 0x70, 0x8c, 0xa2, 0xce, 0xf0, 0xe9, 0xce, 0xa2, 0x8c, 070, 0x40, 0x20, 0x10,
     70     0x10, 0x20, 0x40, 0x70, 0x8c, 0xa2, 0xce, 0xf0, 0xe9, 0xce, 0xa2, 0x8c, 070, 0x40, 0x20, 0x10 };
     71 
     72 static short        fir_output[FIR_OUTPUT_SIZE];
     73 static short        fir_input_0[FIR_INPUT_SIZE];
     74 static const short* fir_input = fir_input_0 + (FIR_KERNEL_SIZE/2);
     75 static short        fir_output_expected[FIR_OUTPUT_SIZE];
     76 
     77 /* This is a trivial JNI example where we use a native method
     78  * to return a new VM String. See the corresponding Java source
     79  * file located at:
     80  *
     81  *   apps/samples/hello-neon/project/src/com/example/neon/HelloNeon.java
     82  */
     83 jstring
     84 Java_com_example_neon_HelloNeon_stringFromJNI( JNIEnv* env,
     85                                                jobject thiz )
     86 {
     87     //char*  str;
     88     char str[512] = {0};
     89     uint64_t features;
     90     char buffer[512];
     91     char tryNeon = 0;
     92     double  t0, t1, time_c, time_neon;
     93 
     94     /* setup FIR input - whatever */
     95     {
     96         int  nn;
     97         for (nn = 0; nn < FIR_INPUT_SIZE; nn++) {
     98             fir_input_0[nn] = (5*nn) & 255;
     99         }
    100         fir_filter_c(fir_output_expected, fir_input, fir_kernel, FIR_OUTPUT_SIZE, FIR_KERNEL_SIZE);
    101     }
    102 
    103     /* Benchmark small FIR filter loop - C version */
    104     t0 = now_ms();
    105     {
    106         int  count = FIR_ITERATIONS;
    107         for (; count > 0; count--) {
    108             fir_filter_c(fir_output, fir_input, fir_kernel, FIR_OUTPUT_SIZE, FIR_KERNEL_SIZE);
    109         }
    110     }
    111     t1 = now_ms();
    112     time_c = t1 - t0;
    113 
    114     sprintf(str, "FIR Filter benchmark:\nC version    : %g ms\n", time_c);
    115     //asprintf(&str, "FIR Filter benchmark:\nC version          : %g ms\n", time_c);
    116     strlcpy(buffer, str, sizeof buffer);
    117 
    118     //free(str);
    119 
    120     strlcat(buffer, "Neon version   : ", sizeof buffer);
    121 
    122     if (android_getCpuFamily() != ANDROID_CPU_FAMILY_ARM) {
    123         strlcat(buffer, "Not an ARM CPU !\n", sizeof buffer);
    124         goto EXIT;
    125     }
    126 
    127     features = android_getCpuFeatures();
    128     if ((features & ANDROID_CPU_ARM_FEATURE_ARMv7) == 0) {
    129         strlcat(buffer, "Not an ARMv7 CPU !\n", sizeof buffer);
    130         goto EXIT;
    131     }
    132 
    133     /* HAVE_NEON is defined in Android.mk ! */
    134 #ifdef HAVE_NEON
    135     if ((features & ANDROID_CPU_ARM_FEATURE_NEON) == 0) {
    136         strlcat(buffer, "CPU doesn't support NEON !\n", sizeof buffer);
    137         goto EXIT;
    138     }
    139 
    140     /* Benchmark small FIR filter loop - Neon version */
    141     t0 = now_ms();
    142     {
    143         int  count = FIR_ITERATIONS;
    144         for (; count > 0; count--) {
    145             fir_filter_neon_intrinsics(fir_output, fir_input, fir_kernel, FIR_OUTPUT_SIZE, FIR_KERNEL_SIZE);
    146         }
    147     }
    148     t1 = now_ms();
    149     time_neon = t1 - t0;
    150     sprintf(str, "%g ms   (x%g faster)\n", time_neon, time_c / (time_neon < 1e-6 ? 1. : time_neon));
    151     //asprintf(&str, "%g ms (x%g faster)\n", time_neon, time_c / (time_neon < 1e-6 ? 1. : time_neon));
    152     strlcat(buffer, str, sizeof buffer);
    153     //free(str);
    154 
    155     /* check the result, just in case */
    156     {
    157         int  nn, fails = 0;
    158         for (nn = 0; nn < FIR_OUTPUT_SIZE; nn++) {
    159             if (fir_output[nn] != fir_output_expected[nn]) {
    160                 if (++fails < 16)
    161                     D("neon[%d] = %d expected %d", nn, fir_output[nn], fir_output_expected[nn]);
    162             }
    163         }
    164         D("%d fails\n", fails);
    165     }
    166 #else /* !HAVE_NEON */
    167     strlcat(buffer, "Program not compiled with ARMv7 support !\n", sizeof buffer);
    168 #endif /* !HAVE_NEON */
    169 EXIT:
    170     //return (*env)->NewStringUTF(env, buffer); // C Version
    171     return env->NewStringUTF(buffer); // C++ Version
    172 }
    173 
    174 #ifdef __cplusplus
    175 }
    176 #endif
    View Code

    二、第二种方法:
    1. helloneon.cpp的修改如下

      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  */
     17 #include <jni.h>
     18 #include <time.h>
     19 #include <stdio.h>
     20 #include <stdlib.h>
     21 #include <cpu-features.h>
     22 #include "helloneon-intrinsics.h"
     23 
     24 #define DEBUG 0
     25 
     26 #if DEBUG
     27 #include <android/log.h>
     28 #  define  D(x...)  __android_log_print(ANDROID_LOG_INFO,"helloneon",x)
     29 #else
     30 #  define  D(...)  do {} while (0)
     31 #endif
     32 
     33 #ifdef __cplusplus
     34 extern "C" {
     35 #endif
     36 
     37 #define  LOG_TAG    "helloneon"
     38 #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
     39 static JavaVM *gJVM;
     40 static const char *classPathName = "com/example/neon/HelloNeon";
     41 
     42 /* return current time in milliseconds */
     43 static double
     44 now_ms(void)
     45 {
     46     struct timespec res;
     47     clock_gettime(CLOCK_REALTIME, &res);
     48     return 1000.0*res.tv_sec + (double)res.tv_nsec/1e6;
     49 }
     50 
     51 
     52 /* this is a FIR filter implemented in C */
     53 static void
     54 fir_filter_c(short *output, const short* input, const short* kernel, int width, int kernelSize)
     55 {
     56     int  offset = -kernelSize/2;
     57     int  nn;
     58     for (nn = 0; nn < width; nn++) {
     59         int sum = 0;
     60         int mm;
     61         for (mm = 0; mm < kernelSize; mm++) {
     62             sum += kernel[mm]*input[nn+offset+mm];
     63         }
     64         output[nn] = (short)((sum + 0x8000) >> 16);
     65     }
     66 }
     67 
     68 #define  FIR_KERNEL_SIZE   32
     69 #define  FIR_OUTPUT_SIZE   2560
     70 #define  FIR_INPUT_SIZE    (FIR_OUTPUT_SIZE + FIR_KERNEL_SIZE)
     71 #define  FIR_ITERATIONS    600
     72 
     73 static const short  fir_kernel[FIR_KERNEL_SIZE] = {
     74     0x10, 0x20, 0x40, 0x70, 0x8c, 0xa2, 0xce, 0xf0, 0xe9, 0xce, 0xa2, 0x8c, 070, 0x40, 0x20, 0x10,
     75     0x10, 0x20, 0x40, 0x70, 0x8c, 0xa2, 0xce, 0xf0, 0xe9, 0xce, 0xa2, 0x8c, 070, 0x40, 0x20, 0x10 };
     76 
     77 static short        fir_output[FIR_OUTPUT_SIZE];
     78 static short        fir_input_0[FIR_INPUT_SIZE];
     79 static const short* fir_input = fir_input_0 + (FIR_KERNEL_SIZE/2);
     80 static short        fir_output_expected[FIR_OUTPUT_SIZE];
     81 
     82 /* This is a trivial JNI example where we use a native method
     83  * to return a new VM String. See the corresponding Java source
     84  * file located at:
     85  *
     86  *   apps/samples/hello-neon/project/src/com/example/neon/HelloNeon.java
     87  */
     88 static jstring stringforneon( JNIEnv* env, jobject thiz )
     89 {
     90     //char*  str;
     91     char str[512] = {0};
     92     uint64_t features;
     93     char buffer[512];
     94     char tryNeon = 0;
     95     double  t0, t1, time_c, time_neon;
     96 
     97     /* setup FIR input - whatever */
     98     {
     99         int  nn;
    100         for (nn = 0; nn < FIR_INPUT_SIZE; nn++) {
    101             fir_input_0[nn] = (5*nn) & 255;
    102         }
    103         fir_filter_c(fir_output_expected, fir_input, fir_kernel, FIR_OUTPUT_SIZE, FIR_KERNEL_SIZE);
    104     }
    105 
    106     /* Benchmark small FIR filter loop - C version */
    107     t0 = now_ms();
    108     {
    109         int  count = FIR_ITERATIONS;
    110         for (; count > 0; count--) {
    111             fir_filter_c(fir_output, fir_input, fir_kernel, FIR_OUTPUT_SIZE, FIR_KERNEL_SIZE);
    112         }
    113     }
    114     t1 = now_ms();
    115     time_c = t1 - t0;
    116 
    117     sprintf(str, "FIR Filter benchmark:\nC version    : %g ms\n", time_c);
    118     //asprintf(&str, "FIR Filter benchmark:\nC version          : %g ms\n", time_c);
    119     strlcpy(buffer, str, sizeof buffer);
    120 
    121     //free(str);
    122 
    123     strlcat(buffer, "Neon version   : ", sizeof buffer);
    124 
    125     if (android_getCpuFamily() != ANDROID_CPU_FAMILY_ARM) {
    126         strlcat(buffer, "Not an ARM CPU !\n", sizeof buffer);
    127         goto EXIT;
    128     }
    129 
    130     features = android_getCpuFeatures();
    131     if ((features & ANDROID_CPU_ARM_FEATURE_ARMv7) == 0) {
    132         strlcat(buffer, "Not an ARMv7 CPU !\n", sizeof buffer);
    133         goto EXIT;
    134     }
    135 
    136     /* HAVE_NEON is defined in Android.mk ! */
    137 #ifdef HAVE_NEON
    138     if ((features & ANDROID_CPU_ARM_FEATURE_NEON) == 0) {
    139         strlcat(buffer, "CPU doesn't support NEON !\n", sizeof buffer);
    140         goto EXIT;
    141     }
    142 
    143     /* Benchmark small FIR filter loop - Neon version */
    144     t0 = now_ms();
    145     {
    146         int  count = FIR_ITERATIONS;
    147         for (; count > 0; count--) {
    148             fir_filter_neon_intrinsics(fir_output, fir_input, fir_kernel, FIR_OUTPUT_SIZE, FIR_KERNEL_SIZE);
    149         }
    150     }
    151     t1 = now_ms();
    152     time_neon = t1 - t0;
    153     sprintf(str, "%g ms   (x%g faster)\n", time_neon, time_c / (time_neon < 1e-6 ? 1. : time_neon));
    154     //asprintf(&str, "%g ms (x%g faster)\n", time_neon, time_c / (time_neon < 1e-6 ? 1. : time_neon));
    155     strlcat(buffer, str, sizeof buffer);
    156     //free(str);
    157 
    158     /* check the result, just in case */
    159     {
    160         int  nn, fails = 0;
    161         for (nn = 0; nn < FIR_OUTPUT_SIZE; nn++) {
    162             if (fir_output[nn] != fir_output_expected[nn]) {
    163                 if (++fails < 16)
    164                     D("neon[%d] = %d expected %d", nn, fir_output[nn], fir_output_expected[nn]);
    165             }
    166         }
    167         D("%d fails\n", fails);
    168     }
    169 #else /* !HAVE_NEON */
    170     strlcat(buffer, "Program not compiled with ARMv7 support !\n", sizeof buffer);
    171 #endif /* !HAVE_NEON */
    172 EXIT:
    173     //return (*env)->NewStringUTF(env, buffer); // C Version
    174     return env->NewStringUTF(buffer); // C++ Version
    175 }
    176 
    177 static JNINativeMethod methods[] = {
    178         {"stringFromJNI","()Ljava/lang/String;", (void*) stringforneon },
    179 };
    180 
    181 /*
    182  * Register several native methods for one class.
    183  */
    184 static int registerNativeMethods(JNIEnv* env, const char* className,
    185         JNINativeMethod* gMethods, int numMethods) {
    186     jclass clazz;
    187 
    188     clazz = env->FindClass(className);
    189     if (clazz == NULL) {
    190         D(ANDROID_LOG_INFO, LOG_TAG, "clazz == NULL");
    191         return JNI_FALSE;
    192     }
    193 
    194     if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
    195         D(ANDROID_LOG_INFO, LOG_TAG,
    196                 "RegisterNatives failed for");
    197         //LOGE("RegisterNatives failed for '%s'", className);
    198         return JNI_FALSE;
    199     }
    200 
    201     return JNI_TRUE;
    202 }
    203 
    204 /*
    205  * Register native methods for all classes we know about.
    206  *
    207  * returns JNI_TRUE on success.
    208  */
    209 static int registerNatives(JNIEnv* env) {
    210     if (!registerNativeMethods(env, classPathName, methods,
    211             sizeof(methods) / sizeof(methods[0]))) {
    212         return JNI_FALSE;
    213     }
    214 
    215     return JNI_TRUE;
    216 }
    217 
    218 int jniThrowException(JNIEnv* env, const char* className, const char* msg) {
    219     jclass exceptionClass = env->FindClass(className);
    220     if (exceptionClass == NULL)
    221         return -1;
    222 
    223     if (env->ThrowNew(exceptionClass, msg) != JNI_OK) {
    224     }
    225 
    226     return 0;
    227 }
    228 JNIEnv* getJNIEnv() {
    229     JNIEnv* env = NULL;
    230     if (gJVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
    231         return NULL;
    232 
    233     return env;
    234 }
    235 jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    236     JNIEnv* env = NULL;
    237     jint result = -1;
    238     gJVM = vm;
    239     D(ANDROID_LOG_INFO, LOG_TAG, "JNI_OnLoad");
    240     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
    241         return result;
    242 
    243     if (registerNatives(env) != JNI_TRUE)
    244         goto end;
    245 
    246     result = JNI_VERSION_1_4;
    247 
    248 end:
    249     return result;
    250 }
    251 
    252 #ifdef __cplusplus
    253 }
    254 #endif
    View Code

    2.其他改动部分同方法一。

    不明问题:
    stringforneon 的返回类型 只能为 jstring 不能用 string。
    参考
    http://blog.csdn.net/martingang/article/details/8170940

    如果提示错误:error: #error You must enable NEON instructions (e.g. -mfloat-abi=softfp -mfpu=neon) to use arm_neon.h
    Android.mk 需要添加两句
    1.LOCAL_SRC_FILES := helloneon.cpp 下面添加
    TARGET_ARCH_ABI := armeabi-v7a
    2.LOCAL_CFLAGS := -DHAVE_NEON=1 后边添加 -mfloat-abi=softfp -mfpu=neon -march=armv7-a
    即是  LOCAL_CFLAGS := -DHAVE_NEON=1 -mfloat-abi=softfp -mfpu=neon -march=armv7-a

    参考
    http://blog.sina.com.cn/s/blog_92c104590101jiyi.html

  • 相关阅读:
    ubuntu更换阿里源
    记一次开源软件的篡改
    linux下搜索指定内容
    随笔_1
    单细胞中的细胞类型划分
    scDNA-seq genomic analysis pipline
    NIH周三讲座视频爬虫
    ggplot2_bubble
    TCGA数据批量下载
    lncRNA芯片重注释
  • 原文地址:https://www.cnblogs.com/zzugyl/p/3090710.html
Copyright © 2011-2022 走看看