首页 > 编程语言 >1、Android 移植C++ 开发的第三方.so包和.a包

1、Android 移植C++ 开发的第三方.so包和.a包

时间:2022-09-28 12:10:20浏览次数:84  
标签:linux androideabi library libraries so C++ ubuntu Android arm


 基本思想:

因为本人不会写android ,所以android 主要以JNI学习为主

方案一:首先搭建一个Android的最基本工程,完成Android 调用c++ 的代码;

方案二:然后本地写一个c++的子模块,使用配置好的(arm-linux-androideabi-gcc/g++)进行编译得到.a 最后将本地编译的.a文件移植到Android工程上,完成Android-->c++ 工程---->(pc端交叉编译的.a) 完成调用;

方案三:直接在c++中引交叉编译的so文件使用

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

方案一:

第一步、首先建立一个基本的Android 工程,然后写入Android调用c++ 的函数模块;

1、Android 移植C++ 开发的第三方.so包和.a包_android studio

MainActivity 修改了默认的设置

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {

// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);
// Example of a call to a native method
//TextView tv = findViewById(R.id.sample_text);
TextView tv = new TextView(this);
testA aaa=new testA();
String text=aaa.way();
tv.setText(text);
setContentView(tv);
}

/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/

public native int add(int a,int b,int []c);
}

testA文件内容

package com.example.myapplication;

public class testA {

public String way(){

//tv.setText(stringFromJNI());
int c[] ={1,2,3,4,5,6,7,8,8,9,9,1};
int sum = add(2, 3,c);
return "2 + 3 = " + Integer.toString(sum);
}

public native int add(int a,int b,int []c);
}

native-lib.cpp文件

#include <jni.h>
#include <string>
#include<iostream>

#include "info.h"
//#include <Eigen/Dense>
using namespace std;
extern "C" {


int total(int t,int g) {
return t*g;
}



JNIEXPORT jint JNICALL
Java_com_example_myapplication_testA_add( JNIEnv* env,
jobject ,
jint a,
jint b,
jintArray arr)
{
jint *carr;
carr = env->GetIntArrayElements(arr, JNI_FALSE);

if(carr == NULL) {
return 0;
}

jint sum = 0;
for(int i=0; i<10; i++) {
sum += carr[i];
}
INFO *info= new INFO();
int c=info->compute(a,b);
delete info;
int z=total(c,c);
return (z+sum);
}

}

info.h头文件

#ifndef MY_APPLICATION_INFO_H
#define MY_APPLICATION_INFO_H

class INFO
{

public:
int compute(int a,int b);

};
#endif //MY_APPLICATION_INFO_H

info.cpp文件

//
#include "info.h"

int INFO::compute(int a,int b)
{

return a+b;
}

CmakeLists.txt文件

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib

# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
native-lib.cpp
info.cpp
)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
log-lib

# Specifies the name of the NDK library that
# you want CMake to locate.
log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
native-lib

# Links the target library to the log library
# included in the NDK.
${log-lib}
)

然后点击允执行效果如下(使用sevensquare 连接手机,点击Android stdio 运行,Android Stdio 环境配置自己解决)

1、Android 移植C++ 开发的第三方.so包和.a包_linux_02

启用Android stdio的默认工程讲述

方案二:

然后在本第编译XXX.a文件;首先在ubuntu 16.04 下载​​https://dl.google.com/android/repository/android-ndk-r21d-linux-x86_64.zip​​建立交叉编译器,

ubutnu@ubuntu:sudo apt-get install gcc-arm-linux-gnueabi  
ubutnu@ubuntu:sudo apt-get install g++-arm-linux-gnueabi
ubutnu@ubuntu:sudo apt-get install gcc-arm-linux-gnueabihf
ubutnu@ubuntu:sudo apt-get install g++-arm-linux-gnueabihf
ubutnu@ubuntu:sudo apt-get install python
ubutnu@ubuntu:axel -n 100 https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip

ubuntu@ubutnu:~$ unzip android-ndk-r21e-linux-x86_64.zip

ubuntu@ubutnu:~$ sudo cp -r android-ndk-r21e /usr/local/
ubuntu@ubuntu:/usr/local/android-ndk-r21e$ sudo ./build/tools/make-standalone-toolchain.sh --toolchain=arm-linux-androideabi-4.9
ubuntu@ubuntu:/usr/local/android-ndk-r21e$ sudo cp /tmp/ndk-root/arm-linux-androideabi.tar.bz2 ../
ubuntu@ubuntu:/usr/local$ sudo tar -jxvf arm-linux-androideabi.tar.bz2

ubuntu@ubutnu:/usr/local/arm-linux-androideabi/bin$ pwd
/usr/local/arm-linux-androideabi/bin

ubuntu@ubutnu:/usr/local/android-ndk-r21e$ pwd
/usr/local/android-ndk-r21e


填入环境变量
ubuntu@ubutnu:/usr/local$ sudo vim ~/.bashrc
ubuntu@ubutnu:/usr/local$ source ~/.bashrc

export ANDROID_SDK=/usr/local/android-sdk-linux
export PATH=${PATH}:$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools
export ANDROID_NDK=/usr/local/android-ndk-r21e
export ARM_TOOL=/usr/local/arm-linux-androideabi/bin
export PATH=$ANDROID_NDK:$ARM_TOOL:$PATH

查看编译是否成功

ubuntu@ubutnu:/usr/local$ arm + TAB 键 
ubuntu@ubutnu:/usr/local$ arm
arm arm-none-linux-gnueabi-addr2line
arm2hpdl arm-none-linux-gnueabi-ar
arm-linux-addr2line arm-none-linux-gnueabi-as
arm-linux-androideabi-addr2line arm-none-linux-gnueabi-c++
arm-linux-androideabi-ar arm-none-linux-gnueabi-c++filt
arm-linux-androideabi-as arm-none-linux-gnueabi-cpp
arm-linux-androideabi-c++filt arm-none-linux-gnueabi-g++
arm-linux-androideabi-clang arm-none-linux-gnueabi-gcc
arm-linux-androideab
....

先插入一个例子测试一下交叉编译器是否可用

ubuntu@ubuntu:~$ cat c.c
#include<stdio.h>
int main()
{
printf("%s","hello world\n");
return 0;
}
ubuntu@ubuntu:~$ arm-linux-androideabi-gcc -static c.c -o helloword
ubuntu@ubuntu:~$ adb push helloword /data/
5340 KB/s (3445564 bytes in 0.630s)
ubuntu@ubuntu:~$ adb shell
root@phone:/ # cd /data/
root@phone:/data # ./helloword
hello world
root@phone:/data #

Android设备测试通过;

在本地写一个function.cpp文件

#include<stdio.h>

int fun(int a,int b)
{
return a+b;
}
ubutnu@ubuntu: arm-linux-androideabi-g++ -shared -fPIC function.cpp -o libfunction.so 

上述要注意,一定要生成libxxx.so 否则找不到这个动态库文件,然后 新建一个Android 的工程

ubuntu@ubuntu:MyApplication2$ tree -l
.
├── app
│ ├── app.iml
│ ├── build
│ │ ├── generated
│ │ │ └── source
│ │ │ └── buildConfig
│ │ │ ├── androidTest
│ │ │ │ └── debug
│ │ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── myapplication
│ │ │ │ └── test
│ │ │ │ └── BuildConfig.java
│ │ │ └── debug
│ │ │ └── com
│ │ │ └── example
│ │ │ └── myapplication
│ │ │ └── BuildConfig.java
│ │ ├── intermediates
│ │ │ ├── apk_list
│ │ │ │ └── debug
│ │ │ │ └── mainApkListPersistenceDebug
│ │ │ │ └── apk-list.gson
│ │ │ ├── bundle_manifest
│ │ │ │ └── debug
│ │ │ │ └── processDebugManifest
│ │ │ │ └── bundle-manifest
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── output.json
│ │ │ ├── check_manifest_result
│ │ │ │ └── debug
│ │ │ │ └── checkDebugManifest
│ │ │ │ └── out
│ │ │ ├── cmake
│ │ │ │ └── debug
│ │ │ │ └── obj
│ │ │ │ └── x86
│ │ │ ├── compatible_screen_manifest
│ │ │ │ └── debug
│ │ │ │ └── createDebugCompatibleScreenManifests
│ │ │ │ └── out
│ │ │ │ └── output.json
│ │ │ ├── instant_app_manifest
│ │ │ │ └── debug
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── output.json
│ │ │ ├── lint_jar
│ │ │ │ └── global
│ │ │ │ └── prepareLintJar
│ │ │ ├── lint_publish_jar
│ │ │ │ └── global
│ │ │ │ └── prepareLintJarForPublish
│ │ │ ├── manifest_merge_blame_file
│ │ │ │ ├── debug
│ │ │ │ │ └── manifest-merger-blame-debug-report.txt
│ │ │ │ └── debugAndroidTest
│ │ │ │ └── manifest-merger-blame-debug-androidTest-report.txt
│ │ │ ├── merged_manifests
│ │ │ │ ├── debug
│ │ │ │ │ ├── AndroidManifest.xml
│ │ │ │ │ └── output.json
│ │ │ │ └── debugAndroidTest
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── output.json
│ │ │ ├── metadata_feature_manifest
│ │ │ │ └── debug
│ │ │ │ └── processDebugManifest
│ │ │ │ └── metadata-feature
│ │ │ │ └── output.json
│ │ │ └── tmp
│ │ │ └── manifest
│ │ │ └── androidTest
│ │ │ └── debug
│ │ └── outputs
│ │ └── logs
│ │ └── manifest-merger-debug-report.txt
│ ├── build.gradle
│ ├── libs
│ ├── proguard-rules.pro
│ └── src
│ ├── androidTest
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── myapplication
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── cpp
│ │ │ ├── CMakeLists.txt
│ │ │ └── native-lib.cpp
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── myapplication
│ │ │ └── MainActivity.java
│ │ └── res
│ │ ├── drawable
│ │ │ └── ic_launcher_background.xml
│ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ ├── layout
│ │ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher_round.xml
│ │ │ └── ic_launcher.xml
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── myapplication
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
├── My Application.iml
└── settings.gradle

90 directories, 52 files

工程界面

1、Android 移植C++ 开发的第三方.so包和.a包_linux_03

在这个目录下建立一个文件夹,将so文件拖入进去,参考(Android:JNI与NDK(二)交叉编译与动态库,静态库 - WangLei_ClearHeart ) 动态库只能建立在该文件夹下 jniLibs,静态库无所谓~~

1、Android 移植C++ 开发的第三方.so包和.a包_c++_04

然后将CMakeLists.txt 拖到这里,填入相应的内容:

1、Android 移植C++ 开发的第三方.so包和.a包_linux_05

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
native-lib

# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
log-lib

# Specifies the name of the NDK library that
# you want CMake to locate.
log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a")

target_link_libraries( # Specifies the target library.
native-lib
function

# Links the target library to the log library
# included in the NDK.
${log-lib})

因为移动了CMakeLIsts.txt的位置,需要修改一下这个文件build.gradle

1、Android 移植C++ 开发的第三方.so包和.a包_ubuntu_06

然后在代码中写入调用的函数即可

1、Android 移植C++ 开发的第三方.so包和.a包_c++_07

native-lib.cpp 文件 (这里需要自己写明函数声明,实际大型工程中,是调用include文件夹的头文件的,具体可以参考后续方案三)

1、Android 移植C++ 开发的第三方.so包和.a包_android studio_08

然后点击运行就可以调用了,这里没有打印显示

1、Android 移植C++ 开发的第三方.so包和.a包_c++_09

静态库的编译

ubuntu@ubuntu:~/project/src$ arm-linux-androideabi-g++ -shared -fPIC function.cpp -o libfunction.so 
ubuntu@ubuntu:~/project/src$ ls
function.cpp libfunction.so Untitled Document
ubuntu@ubuntu:~/project/src$ arm-linux-androideabi-ar r staticfunction.a libfunction.so
arm-linux-androideabi-ar: creating staticfunction.a

填入工程目录

1、Android 移植C++ 开发的第三方.so包和.a包_linux_10

然后修改对应的文件CMakelists.txt

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
native-lib

# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
log-lib

# Specifies the name of the NDK library that
# you want CMake to locate.
log)
add_library(function STATIC IMPORTED)

set_target_properties(function PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/staticlibs/staticfunction.a)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
native-lib
function
# Links the target library to the log library
# included in the NDK.
${log-lib})

可以运行了,结果正常~~

1、Android 移植C++ 开发的第三方.so包和.a包_android_11

方案三:

创建Android的c++ 工程,调用动态库交叉编译器生成的so文件,使用独立的头文件和独立的so文件,这种方式常见于官方提供的源代码和大型工程中(需要使用构建的交叉编译器NDK编译文件):

ubuntu@ubuntu:~$ cat function.cpp 
#include<iostream>
#include "function.h"
int fun(int a,int b)
{
return a+b;
}
ubuntu@ubuntu:~$ cat function.h
#include<iostream>
int fun(int a,int b);
ubuntu@ubuntu:~$ arm-linux-androideabi-g++ -c function.cpp -o function.so
ubuntu@ubuntu:~$ ls
function.cpp function.h function.so

然后修改build.gradle文件

1、Android 移植C++ 开发的第三方.so包和.a包_android_12

externalNativeBuild {
cmake {
cppFlags "-std=c++11"
}
ndk{
abiFilters 'armeabi-v7a' // x86 armeabi arm64-v8a x86_64
}
}
}

sourceSets{
main{
jniLibs.srcDirs=["src/main/jniLibs/libs"]
}
}

修改CmakeLists.txt 文件内容为:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

include_directories(${CMAKE_SOURCE_DIR}/include)

# 导入opencv的so
add_library(function SHARED IMPORTED)
set_target_properties(function PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/../jniLibs/libs/${ANDROID_ABI}/function.so)


add_library( # Sets the name of the library.
native-lib

# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
log-lib

# Specifies the name of the NDK library that
# you want CMake to locate.
log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
native-lib
function
# Links the target library to the log library
# included in the NDK.
${log-lib} )

建议存放的头文件和so文件目录不要修改;

对应的native-lib.cpp文件内容为

#include <jni.h>
#include <string>
#include <iostream>
#include "include/function.h"


using namespace std;
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_boost_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";

cout<<fun(2,3)<<endl;
return env->NewStringUTF(hello.c_str());
}

ok 打通了Android 独立使用c++代码;Android 的c++模块调用.a文件;Android 的c++模块调用.so文件;

关于是调用静态库还是动态库,看个人而言,转化工具NDK也提供了:

ubuntu@ubuntu:~$ ar
ar arm-linux-androideabi-size
arch arm-linux-androideabi-strings
arecord arm-linux-androideabi-strip
arecordmidi armv7a-linux-androideabi16-clang
arm2hpdl armv7a-linux-androideabi16-clang++
arm-linux-androideabi-addr2line armv7a-linux-androideabi17-clang
arm-linux-androideabi-ar armv7a-linux-androideabi17-clang++
arm-linux-androideabi-as armv7a-linux-androideabi18-clang
arm-linux-androideabi-c++ armv7a-linux-androideabi18-clang++
arm-linux-androideabi-c++filt armv7a-linux-androideabi19-clang
arm-linux-androideabi-clang armv7a-linux-androideabi19-clang++
arm-linux-androideabi-clang++ armv7a-linux-androideabi21-clang
arm-linux-androideabi-cpp armv7a-linux-androideabi21-clang++
arm-linux-androideabi-dwp armv7a-linux-androideabi22-clang
arm-linux-androideabi-elfedit armv7a-linux-androideabi22-clang++
arm-linux-androideabi-g++ armv7a-linux-androideabi23-clang
arm-linux-androideabi-gcc armv7a-linux-androideabi23-clang++
arm-linux-androideabi-gcc-4.9 armv7a-linux-androideabi24-clang
arm-linux-androideabi-gcc-4.9.x armv7a-linux-androideabi24-clang++
arm-linux-androideabi-gcc-ar armv7a-linux-androideabi26-clang
arm-linux-androideabi-gcc-nm armv7a-linux-androideabi26-clang++
arm-linux-androideabi-gcc-ranlib armv7a-linux-androideabi27-clang
arm-linux-androideabi-gcov armv7a-linux-androideabi27-clang++

补充:如果你编译的库含有第三方的头文件,可以只引入头文件即可

标签:linux,androideabi,library,libraries,so,C++,ubuntu,Android,arm
From: https://blog.51cto.com/u_12504263/5719122

相关文章