unity 呼叫C++庫(android+jni+window dll平臺實現)
方便不知道如何再unity呼叫各平臺動態庫的同學參考,實測可用:
window案例
動態庫名
tracker_model.dll
位置
unity工程 Assets\Plugins目錄下
c# 關鍵呼叫
程式碼
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
using System.Collections.Generic;
//[StructLayout(LayoutKind.Sequential)]
public struct Point3F {
public float x;
public float y;
public float z;
}
public class Control : MonoBehaviour {
System.IntPtr center_data_prt;
System.IntPtr fingertips_data_prt;
[DllImport("tracker_model")]
public static extern long points_init (string iin);
........
void Start () {
handle = points_init(fileName);
...................
center_data_prt = Marshal. AllocHGlobal(Marshal.SizeOf(typeof(Point3F)));
fingertips_data_prt = Marshal. AllocHGlobal(Marshal.SizeOf(typeof(Point3F))*maxFingerTips);
tri_cnt = points_get_fingertips(handle, center_data_prt, fingertips_data_prt
}
void Update () {
Point3F center = (Point3F)Marshal.PtrToStructure(
(System.IntPtr)(center_data_prt.ToInt64()),typeof(Point3F));
for (int i = 0; i < tri_cnt; i++) {
Point3F point = (Point3F)Marshal.PtrToStructure(
(System.IntPtr)(fingertips_data_prt.ToInt64()+i*Marshal.SizeOf(typeof(Point3F))),typeof(Point3F));
}
}
void OnDestroy(){
Marshal.FreeHGlobal(center_data_prt);
Marshal.FreeHGlobal(fingertips_data_prt);
}
對應tracker_model.dll c++標頭檔案介面
#ifndef _model_api_H_
#define _model_api_H_
#ifdef WIN32
#ifdef HTM_DLL_EXPORT
#define HTM_API extern "C" _declspec(dllexport)
#else
#define HTM_API extern "C" _declspec(dllimport)
#endif
#else
#define HTM_API
#endif
struct Point3F
{
float x;
float y;
float z;
};
HTM_API long points_init(const char *config_file);
HTM_API int points_get_tri(long handle, Point3F* triangle_vertex_list, int list_len);
~~~~~~~
具體動態庫編譯過程不敘述
Android jni
*/ 1 unity使用c#呼叫android函式案例 製作unity的android外掛(具體流程百度) 建立完外掛和目錄後 unity工程下有Assets\Plugins\Android\libs目錄 2 eclipse下利用jni製作c++庫如下 h檔案=========================== #include <jni.h>
/* Header for class com_example_pluginar_arlib_JniAr */ #ifndef _Included_com_example_pluginar_arlib_JniAr
#define _Included_com_example_pluginar_arlib_JniAr
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_pluginar_arlib_JniAr
* Method: getVersion
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_pluginar_arlib_JniAr_getVersion
(JNIEnv *, jclass); #ifdef __cplusplus
}
#endif
#endif cpp檔案:================ #include <jni.h>
#include "com_example_pluginar_arlib_JniAr.h" JNIEXPORT jstring JNICALL Java_com_example_pluginar_arlib_JniAr_getVersion
(JNIEnv *env, jclass jc){ return env->NewStringUTF("22");
} //下面這個和jni介面無關,是後面測試c#直接呼叫c++介面準備的測試介面 extern "C" {
int getInt(){
return 5;
}
} eclipse自動生成的編譯配置檔案Application.mk
APP_MODULES := Plugin
APP_OPTIM := release
#APP_OPTIM := debug
#APP_ABI := all
APP_ABI := armeabi armeabi-v7a x86 mips
#APP_ABI := armeabi armeabi-v7a x86 mips arm64-v8a x86_64 mips64
APP_PLATFORM := android-8
#NDK_TOOLCHAIN_VERSION := clang 總之最後生成我們需要的各平臺libPlugin.so庫(這些c++庫將被拷貝到unity工程Assets\Plugins\Android\libs目錄下)
對應的在eclipse jni工程中呼叫c++介面的java關鍵程式碼如下 public class Jni {
// Load the native libraries.
static {
// System.loadLibrary("c++_shared");
System.loadLibrary("Plugin"); //載入libPlugin.so
}
static public native String getVersion();
} public class ActivityMain extends UnityPlayerActivity { //unity外掛具體百度
Context mContext;
private LinearLayout u3dLayout;
UnityPlayer mUnityPlayer;
Button bt1;
Button bt2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
u3dLayout = (LinearLayout) findViewById(R.id.u3d_layout);
mUnityPlayer = new UnityPlayer(this);
View playerView = mUnityPlayer.getView();
u3dLayout.addView(playerView);
bt1 = (Button)findViewById(R.id.u3d_button1);
bt2 = (Button)findViewById(R.id.button2);
bt1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(mContext,ActivityArManage.class));
}
});
bt2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, Jni.getVersion(), Toast.LENGTH_LONG).show();
}
});
} // only for test, C# in unity will call it
public int GetInt(){
runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(mContext, "Unity Button test", Toast.LENGTH_LONG).show();
}
});
//send message to Unity object named ArManager
UnityPlayer.UnitySendMessage("ArManager", "ZoomIn", "");
return 1000;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
onDestroy();
}
return true;
}
} 基本的android測試程式碼就搭建完成,如果不放心可以不先做unity外掛不要extends UnityPlayerActivity,只用普通的android工程測試jni是否正確然後再製作unity外掛 unity下程式碼簡單,就是製作android外掛部分麻煩,具體不敘述: using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
using System.Collections.Generic;
publicclassTestAndroidScript:MonoBehaviour{
intn=0;
[DllImport("Plugin")] // 注意工程下libc++庫名是libPlugin.so
publicstaticexternintgetInt();
//Usethisfor initialization
voidStart(){
}
//Updateiscalledonceper frame
voidUpdate(){
}
voidOnGUI(){
if(GUI.Button(newRect(20,20,250,100),"c#androidtest"+n)){
AndroidJavaClassjc=newAndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObjectjo=jc.GetStatic<AndroidJavaObject>("currentActivity");
n+=jo.Call<int>("GetInt");
}
if(GUI.Button(newRect(20,220,250,100),"c#c++test"+getInt())){
}
}
}