1. 程式人生 > >Unity使用NDK在Android平臺上引用C++程式碼的so檔案(下)

Unity使用NDK在Android平臺上引用C++程式碼的so檔案(下)

由於最近進入了公司,手頭上的工作需要一點一點的去適應,所以沒有空來完成接下來的博文,今天突然想到寫一些,發現這麼久沒有接觸了,好像已經忘記了很多,寫下這個博文,我也正好回顧一個這一方面的知識。

關於在unity上使用C++的程式碼需要用到SO檔案了,這就像Cocos上使用C++編寫的遊戲一樣可以執行在Android上也同樣是使用了so檔案。

首先在Android上使用so檔案我們分為下面幾個步驟:

一、NDK環境的搭建

NDK環境的搭建非常簡單,只需在網上下載一個NDK的環境安裝上就可以,安裝好以後會有很多的例子,這裡你也可以參考一下,不想看的,在第二部分我會用一個最簡單的例子帶你編譯成一個簡單的so檔案,這可以增強自己的成就感和增加興趣去往下繼續摸索,到現在為止,你只需要安裝好一個NDK的環境就可以跟我進入下一步的操作,最好呢把NDk加入環境變數中方面一點。

二、so檔案的編譯

首先選擇一個你需要編譯so檔案的專用資料夾,最好是英文路徑,沒試過中文路徑可以不可以(你可以試試),接下來,在你選的那個資料夾下建立一個名為“jni”的資料夾,如下圖:

開啟這個jni資料夾,我們要建立三個檔案:Android.mk 、Application.mk 、testdll.cpp,最後一個檔案是你要編譯的C++檔案,名字你也可以自己取,不過第一個檔案中要注意你要編譯的這個檔名字。

Android.mk檔案

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := testdll
LOCAL_SRC_FILES := testdll.cpp

include $(BUILD_SHARED_LIBRARY)

首先看上面的的module變數和files變數是你要編譯個匯出的模組名字和檔案的名字,改成你需要的檔名和模組名字,最好要一樣,這樣好便於管理和維護,其他的可以先按照我這樣寫

Application.mk檔案

APP_ABI := all
APP_STL := stlport_static 

一個行是用於匯出成什麼檔案的選項,這裡我寫的是ALL,表示匯出所有的型別,後面你可以自己選擇,第二行一定要加上,這個是用於新增靜態的C/C++標頭檔案的,不加的話,後面編譯帶有標頭檔案的程式碼會有找不到標頭檔案的報錯。

testdll.cpp檔案

extern
{   
        static int ReturnNum()
	{
		return 32;
	}
}

這是我寫的測試用的最簡單的C++檔案,用於返回一個數字。記住如果是C++的程式碼一定要使用extern包起來,否則so引用的函式表中找不到這個函式,這是很重要的。測試使用就應該先使用最簡單有效的東西,如果想寫複雜的再慢慢往下探索,這樣便於找出問題的所在。

好了,一切都準備好了,我們開始編譯檔案

開啟命令列,在這裡,如果你添加了環境變數就只需要用命令列開啟到你建立的jni的資料夾下,沒有配環境變數的緊接著往下看,如圖:

然後敲入ndk-build命令靜靜等待片刻,成功後是如下圖這樣:

可以看到創建出了適用於不同平臺的so檔案,這些檔案在你建立的資料夾下的libs資料夾下,並用放在不同平臺使用的資料夾,這樣so檔案就被編譯好了,提示一下,android下使用的so檔案暫時使用armebi-v7a平臺,這個是32位的android,在所有的android上都可以使用的,而v8a只可以在較新的裝置上執行,你可以先用v7a測試看看。

如果你的ndk環境變數沒有配置好,使用下面這個方法,

開啟命令列,同樣開啟到你建立的jni資料夾下面,如圖:

但是,接下來的命令你需要加入你的ndk的絕對路徑

比如:D:\Android\NDK-r10e\ndk-build 這是我的ndk路徑,回車後如下圖:

同樣完成了操作。

三、放到Unity的環境下

我們把編譯好的v7a的so檔案放到上一節我們建立好的unity專案中的Assets\Plugins\Android\libs目錄下,下面我們就可以在unity裡呼叫so檔案中的方法了

四、在unity下的C#程式碼裡如何引用C++程式碼製作成的so檔案

上一節的test.cs腳本里用下面的方法去呼叫,注意下面程式碼中我把上一節的程式碼刪除掉了,可以不刪除的,你們應該可以理解的

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Runtime.InteropServices;
using UnityEngine.UI;

public class test : MonoBehaviour {
    public Text txt;

    [DllImport("testdll")]
    public static extern int ReturnNum();

    void Start()
    {
        txt.text = ReturnNum().ToString();
    }
}

接下來我們打包成apk在模擬器裡執行一下看一看

之前做教程的時候忘記加extern,最後沒有成功,加了extern以後就沒有任何問題了,執行的程式碼可能和上面的有區別,你應該懂得,但呼叫的地方沒有任何區別,如果有任何疑問可以給我留言