您的位置:首页 > 移动开发 > Unity3D

unity 调用C++库(android+jni+window dll平台实现)

2016-07-07 15:27 621 查看
方便不知道如何再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

(android ndk 编译c++库过程 具体不叙述  jni工程制作也不叙述,网上有  )

jni方法:
/*编译接口类:

 *

 * http://www.2cto.com/kf/201409/330892.html
 *
进入项目文件夹, 生成JNI的头文件, 使用命令:
javah -classpath bin/classes -d jni com.example.hellomyjni.JniClient
命令解析:
javah 生成头文件;
-classpath 使用类的位置(bin/classes), 都是.class文件;
-d jni 需要生成JNI的类(com.example.hellomyjni.JniClient), 包括[package].[classname].
按F5刷新项目, 项目会自动生成jni文件夹, 并包含一个头文件com_example_hellomyjni_JniClient.h.
右键点击项目在Android Tools里面点击Add NativeSupport, 就会自动生成: HelloMyJni.cpp和Android.mk.

*/

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;

public class TestAndroidScript : MonoBehaviour {
    int n = 0;

    [DllImport("Plugin")]
// 注意工程下libc++库名是libPlugin.so
    public static extern int getInt();
    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }

    void OnGUI(){
        if (GUI.Button (new Rect(20,20,250,100),"c# android test"+n )) {
            AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
            n += jo.Call<int>("GetInt");
        }

        if (GUI.Button (new Rect(20,220,250,100),"c# c++test"+getInt() )) {
            
        }
    }
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: