Unity使用c++發佈到android平臺

        最近在做Unity中使用C++的方案,剛開始是用直接打包到Android發現會找不到C++DLL,通過查資料發現Android中不能用C++DLL,需要自己手動打包成android對用的.so文件。

        先將下要用的工具,NDKAndroid SDKAndroidStudio。我的AndroidSutdio用的是2.3.3版本的,下Android SDK相關的最好能能翻牆,不然有可能下載失敗。

        安裝完之後打開AndroidStudio,新建C++項目,注意一定要勾選Include C++選項,然後就一直下一步就可以了,完成之後打開項目配置file->project structure設置下SDK,NDK路徑


,新創建的項目會有一個默認的c++文件,先編譯一下make project,確保默認的文件能編譯通過,這樣說明你的環境沒有問題。編譯默認項目的時候也有可能會遇到報錯,我遇到了SDK的版本和build tool的版本匹配不上,這裏講下解決方法,打開app目錄下的build.gradle文件,修改相應的版本對應自己SDK的版本就行,如果沒有對應的版本需要去下。這裏貼一下我的配置,注意紅框裏面的版本要移植,不然就會編譯報錯。

        確保默認項目沒問題之後開始我們接下來的工作,如果你的工程有多個項目,並且有依賴關係,比如工程裏面有a,b,c三個項目,a是主工程,b,c是提供相關功能的模塊。我們就需要先把b和c在androidstudio裏面編譯成靜態庫的.a文件,然後在編譯主工程編譯依賴着兩個.a文件編譯成.so文件。

        選擇file->new->new module,選android library,,新建完之後在這個目錄下新建一個CMakeLists.txt文件。,cmake的寫法我就不講了,需要的自己百度,我這裏寫了一個例子,可以參考我這個來寫,具體的內容要根據自己的項目來填充。

# 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)

#宏定義 格式 -D_你的宏定義
add_definitions(-D_VISION_MOBILE)
add_definitions(-D_VISION_ANDROID)


#編譯需要引用的頭文件
set(INCLUDE_DIR
    ../../Program/Client/a
    ../../Program/Client/b
)

#引用頭文件
include_directories(${INCLUDE_DIR})

#編譯需要的CPP文件
file(GLOB_RECURSE SRC_FILE
    "../../Program/Client/a/*.cpp"
    "../../Program/Client/b/*.cpp"
    )


#編譯.a文件 STATIC 是生成.a文件 SHARED是生成.so文件
add_library( # Sets the name of the library.
             Client

             # Sets the library as a shared library.
             STATIC

             # Provides a relative path to your source file(s).
             ${SRC_FILE} )

        build.gradle裏面需要加一些配置

apply plugin: 'com.android.library'
apply from: rootProject.getRootDir().getAbsolutePath() + "/utils.gradle"

def stlArg = getSTLArg()
def toolChain = getToolChain()
def abis = getAbiFilters()

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"

    defaultConfig {
        minSdkVersion 22
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"

        externalNativeBuild {
            cmake {
                //abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a'
                for(abi in abis){
                    abiFilters abi
                }
                //https://developer.android.com/ndk/guides/cmake.html#variables
                arguments toolChain,stlArg,'-DANDROID_ARM_MODE=arm','-DANDROID_ARM_NEON=TRUE'
                cFlags '-std=c11'
                cppFlags '-std=c++11', '-fpic', '-fstack-protector', '-frtti', '-fexceptions'
                targets "BaseRace"
            }
        }

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
}

這些都配置完之後就make project,這個時間是最痛苦的時間會有很多報錯,需要耐心慢慢改,我們項目的代碼比較多,我改了兩天多才改完。例如不能引用windows的相關頭文件,調用函數不能用int賦值給uint等等。

    如果你的.a文件存在依賴的關係,只需要把另外依賴的項目相關的頭文件加進去就可以,到最後編譯.so文件的時候在鏈接,不需要再編譯.a文件的時候添加庫依賴。

    好,就這樣編譯完所有的.a文件之後,開始編譯.so文件,.so文件的配置和.a文件有點不一樣。首先是add library裏面要改成SHARED,然後後面要加上相關的依賴。

# 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)

#宏定義
add_definitions(-D_VISION_MOBILE)
add_definitions(-D_VISION_ANDROID)


#編譯需要引用的頭文件
set(INCLUDE_DIR
    ../../Program/c/a
	../../Program/c/b
	E:/SDK1/Sdk/ndk-bundle/sources
)

#引用頭文件
include_directories(${INCLUDE_DIR})

#編譯需要的CPP文件
file(GLOB_RECURSE SRC_FILE
    "../../Program/c/a/*.cpp"
	"../../Program/c/b/*.cpp"
    )


#編譯.so文件
add_library( # Sets the name of the library.
             Client

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             ${SRC_FILE} )

#查找NDK相關的庫文件
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 )
find_library(
            stdc++-lib
            stdc++ )
find_library(
            c-lib
            c )
find_library(
            dl-lib
            dl )
find_library(
            m-lib
            m )
find_library(
            GLESv1_CM-lib
            GLESv1_CM
            )
find_library(
            GLESv2-lib
            GLESv2 )
find_library(
            EGL-lib
            EGL
            )
find_library(
            android-lib
            android )
find_library(
            android_support-lib
            android_support )
find_library(
            c++_static-lib
            c++_static )
			
#添加link依賴項
target_link_libraries( # Specifies the target library.
                            Client
                            "-Wl,--start-group"
                            liba.a
                            libb.a
                            ${android-lib}
                            "-Wl,--end-group"
                            ${GLESv1_CM-lib}
                            ${GLESv2-lib}
                            ${EGL-lib}
                            ${c-lib}
                            ${log-lib}
                            ${dl-lib}
                            ${m-lib}
                            )

需要把liba.a拷貝到cmakelist同級目錄或者制定下相對路徑也行。改好makelist之後編譯,有可能會有鏈接問題,一般都是相關的CPP文件沒有加到.a文件的編譯裏面,回到之前的.a工程在加進去就行了。

    最後編譯出來.so文件放到unity的Assets\Plugins\Android\libs\armeabi-v7a目錄下面,沒有的話創建一個,注意unity,dllimport裏面的名字只需要填去掉lib前綴和.so後綴的。比如你的so叫libClient.so,

    [DllImport("Client")]

        public static extern bool a();

這樣寫就可以了。注意unity build的時候選,不要用默認的FAT,不然會找不到DLL。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章