Liu Shouda coder

ncnn jni

2017-12-06

本文记录ncnn安卓jni编译过程。

使用ncnn example里面的jni直接编的so文件,在ncnn-mobile里面无法直接使用。结果不对。

怀疑是版本jni接口变化。就想着自己编译jni。

先参考wiki编译安卓.a 库。

cmake -DCMAKE_TOOLCHAIN_FILE=../android.toolchain.cmake -DANDROID_ABI="armeabi-v7a with NEON"     -DANDROID_NATIVE_API_LEVEL=android-21 -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 -DCMAKE_BUILD_TYPE=Release -DANDROID_STL_FORCE_FEATURES=OFF ..

有了.a之后,就需要编译jni,并在具体的应用测试正确性。

cmake jni

先从example的eclipse导入项目。发现根本识别不了c++项目。问题又转变成怎么添加jni问题了。

经过一番尝试之后,发现添加jni只要: 添加cmake文件,并且在build gradle里面增加以下配置。

externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }

然后cmake可以指定cpp代码位置。

将ncnn的各个头文件拷贝过来,发现没有platform.h,查看代码后,发现这个头文件似乎没用。把每个地方的platform删掉即可

openmp问题

externalNativeBuild {
            cmake {
                cppFlags "-fopenmp -std=c++11"
                arguments "-DANDROID_TOOLCHAIN=clang"
            }
        }

jnigraphics

在build.gradle里面添加ldLibs “jnigraphics” 死活不成功。

后来在cmake里面添加。

target_link_libraries( squeezencnn
                       ${log-lib}
                       ncnn
                       jnigraphics)

又会报错。 再在cmake加上

find_library(jnigraphics
            jnigraphics)

stl

增加-std=c++11无效,无论在cmake还是在build.gradle 添加上移植一来都能解决问题的以下两句依然无济于事。

externalNativeBuild {
            cmake {
                cppFlags "-std=c++11 -frtti -fexceptions"
                arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_STL=c++_shared"
            }
        }

然后开始怀疑是不会clang和gcc编译不兼容问题。 把上面的clang反复删除多没有用。

感觉是无解状态。

后面怀疑是否gnustl之类的错误。把”-DANDROID_STL=c++_shared”删掉,随手一试,居然就通过了。无所适从。

udpate 2017.12.19:

c++_shared虽然能解决std::to_string, std::stod等问题,但是由于很多第三方库使用的是gnustl,再选择用c++_shared的方式,会导致出错。只能沿用gnustl的方式。

解决方式就是不用to_string, stod这几个函数 :)

在需要使用to_string这几个函数的时候,不用std::to_string而是包含以下这个头文件,然后直接to_string,不加命名空间。

#include <sstream>
#include <string>

#if defined(__ANDROID__)
template <typename T>
std::string to_string(T value)
{
  std::ostringstream os;
  os << value;
  return os.str();
}

inline int stoi(const std::string& str) {
  std::stringstream ss;
  int n = 0;
  ss << str;
  ss >> n;
  return n;
}

inline double stod(const std::string& str, std::size_t* pos = 0) {
  std::stringstream ss;
  ss << str;
  double val = 0;
  ss >> val;
  if (pos) {
    if (ss.tellg() == -1) {
      *pos = str.size();
    } else {
      *pos = ss.tellg();
    }
  }
  return val;
}
#else
using std::to_string;
using std::stoi;
using std::stod;
#endif // defined(__ANDROID__)

上一篇 git入门

下一篇 mxnet to ncnn

Content