Unity3D在IOS、Android上使用C++并回调的究极解决方案
2017-11-17 18:43
525 查看
转载地址:
http://blog.csdn.net/IceTeaSet/article/details/53142929
各种调用C++的方法在各种平台下的总结如下(可能会有出入):
1、在VS中使用CLR C++工程,编译产生.dll,放入Plugins
✔ Android、Editor、Windows、OSX
✘ IOS (报的错貌似与il2cpp有关)
2、直接在Plugins中放入.cpp文件(不支持子目录)
✔ IOS
✘ Editor、Windows、OSX、Android
3、编译出目标移动平台的库(.a或.so等),放入Plugins
✔ IOS、Android
✘ Editor、Windows、OSX
4、编译出PC平台的库,放入Plugins
✔ Windows(.dll)、Linux(.so)、OSX(Bundle)
✘ iOS、Android
? Editor
我的目标主要是IOS,所以下面以IOS、C++为例介绍一下各种解决方案,我的Unity版本是5.4.2f2。(后因为build时崩溃换成5.5.0f3)
无论用哪种方法,都需要在Unity工程中Assets中新建一个Plugins文件夹,再新建一个iOS文件夹。
第一种方案的话,CLR C++的语法与正常C++稍有不同,要改C++代码,而且还不能在iOS上使用,就直接否决了。第四种也不用说,应该行不通。
第二、三种方案根据回调方法的不同每种又可以分为两种方法:使用官方手册上的UnitySendMessage;使用MonoPInvokeCallBack。所以共四种方法。
直接看我将四种方法汇总在一块的代码吧:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
将最后一个代码片用CocoaTouchStaticLibrary工程编译成.a后,与第二个代码片的.cpp一起放到Plugins/iOS文件夹中。Unity在Build时会将Plugins复制到Xcode工程里的Libraries文件夹下。
几个注意事项:
1、尽量不要在XCode里的Libraries/Plugins中直接修改.cpp,因为很容易就被Unity覆盖或者删除了……别问我怎么知道的。如果要在XCode中修改.cpp,那么要么干脆把Unity工程里的Plugins删除,要么可以放到XCode下的Classes文件夹中(官方文档推荐的,说是不会被覆盖)。
2、官方文档说UnitySendMessage是异步的,可能会慢一帧,MonoPInvokeCallBack未知。
3、如果是在Android,可能要将dllimport中的“__Internal”改成“库文件名”。
4、[重要]CocoaTouchStaticLibrary工程的IOS deployment target要设置成和Unity Xcode工程一样,不然链接时会报错。Unity生成的Xcode默认是7.0,郁闷的是现在最低只能选8.0了,只好都改成8.0或者更高。
5、用了extern “C”后namespace就失效了(如上例TestFunc3),注意不要重定义
要是官方文档能更详细一点就好了…
http://blog.csdn.net/IceTeaSet/article/details/53142929
各种调用C++的方法在各种平台下的总结如下(可能会有出入):
1、在VS中使用CLR C++工程,编译产生.dll,放入Plugins
✔ Android、Editor、Windows、OSX
✘ IOS (报的错貌似与il2cpp有关)
2、直接在Plugins中放入.cpp文件(不支持子目录)
✔ IOS
✘ Editor、Windows、OSX、Android
3、编译出目标移动平台的库(.a或.so等),放入Plugins
✔ IOS、Android
✘ Editor、Windows、OSX
4、编译出PC平台的库,放入Plugins
✔ Windows(.dll)、Linux(.so)、OSX(Bundle)
✘ iOS、Android
? Editor
我的目标主要是IOS,所以下面以IOS、C++为例介绍一下各种解决方案,我的Unity版本是5.4.2f2。(后因为build时崩溃换成5.5.0f3)
无论用哪种方法,都需要在Unity工程中Assets中新建一个Plugins文件夹,再新建一个iOS文件夹。
第一种方案的话,CLR C++的语法与正常C++稍有不同,要改C++代码,而且还不能在iOS上使用,就直接否决了。第四种也不用说,应该行不通。
第二、三种方案根据回调方法的不同每种又可以分为两种方法:使用官方手册上的UnitySendMessage;使用MonoPInvokeCallBack。所以共四种方法。
直接看我将四种方法汇总在一块的代码吧:
//C# using UnityEngine; using System.Collections; using System; using System.Runtime.InteropServices; using AOT; public class MonoCB : MonoBehaviour { [StructLayout(LayoutKind.Sequential)] struct Parameter { public int a; public int b; } delegate void CallBack(IntPtr param); [DllImport ("__Internal")] static extern void TestFunc(int a,int b,CallBack cb); [DllImport ("__Internal")] static extern void TestFunc2(int a,int b); [DllImport ("__Internal")] static extern void TestFunc3(int a,int b,CallBack cb); [DllImport ("__Internal")] static extern void TestFunc4(int a,int b); const int CallBackByMonoPInvokeFromCpp = 1; const int CallBackByUnitySendMessageFromCpp = 1; const int CallBackByMonoPInvokeFromLib = 1; const int CallBackByUnitySendMessageFromLib = 1; // Use this for initialization void Start () { RuntimePlatform rp = Application.platform; Debug.Log ("[DQC]:" + rp.ToString ()); if (rp == RuntimePlatform.IPhonePlayer) { if (CallBackByMonoPInvokeFromCpp>0) { Debug.Log ("[DQC]:start accessing cpp TestFunc. "); TestFunc (1,0,CallBackFunc); Debug.Log ("[DQC]:End accessing cpp TestFunc. "); } if (CallBackByUnitySendMessageFromCpp>0) { Debug.Log ("[DQC]:start accessing cpp TestFunc2. "); TestFunc2 (2,0); Debug.Log ("[DQC]:End accessing cpp TestFunc2. "); } if (CallBackByMonoPInvokeFromLib>0) { Debug.Log ("[DQC]:start accessing cpp TestFunc3. "); TestFunc3 (3,0,CallBackFunc3); Debug.Log ("[DQC]:End accessing cpp TestFunc3. "); } if (CallBackByUnitySendMessageFromLib>0) { Debug.Log ("[DQC]:start accessing cpp TestFunc4. "); TestFunc4 (4,0); Debug.Log ("[DQC]:End accessing cpp TestFunc4. "); } } else if (rp == RuntimePlatform.OSXEditor || rp == RuntimePlatform.OSXPlayer) Debug.Log ("[DQC]:need to run in a real iphone to access cpp."); } // Update is called once per frame void Update () { } [MonoPInvokeCallback(typeof(CallBack))] static void CallBackFunc(IntPtr param) { var p = (Parameter)Marshal.PtrToStructure(param, typeof(Parameter)); Debug.Log("[DQC]:CallBackFunc. a:" + p.a + " b:" + p.b); } void CallBackFunc2(string message) { Debug.Log("[DQC]:CallBackFunc2. Message is:"+ message); } [MonoPInvokeCallback(typeof(CallBack))] static void CallBackFunc3(IntPtr param) { var p = (Parameter)Marshal.PtrToStructure(param, typeof(Parameter)); Debug.Log("[DQC]:CallBackFunc3. a:" + p.a + " b:" + p.b); } void CallBackFunc4(string message) { Debug.Log("[DQC]:CallBackFunc4. Message is:"+ message); } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//C++ 直接用.cpp #include <iostream> using namespace std; extern "C" { typedef struct Parameter { int a; int b; } Param; typedef void(*CallBack)(Param* p); void TestFunc(int a,int b,CallBack cb) { cout<<"[DQC]:in TestFunc.a:"<<a<<" b:"<<b<<endl; Param p; p.a = a; p.b = b; cb(&p); } void TestFunc2(int a,int b) { cout<<"[DQC]:in TestFunc2.a:"<<a<<" b:"<<b<<endl; UnitySendMessage("Main Camera","CallBackFunc2","[DQC]:success from TestFunc2"); } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//C++ 编译成.a 与上面几乎一样 #include <iostream> using namespace std; extern "C" { typedef struct Parameter { int a; int b; } Param; typedef void(*CallBack)(Param* p); namespace IvesTest{ void TestFunc3(int a,int b,CallBack cb) { cout<<"[DQC]:in TestFunc3.a:"<<a<<" b:"<<b<<endl; Param p; p.a = a; p.b = b; cb(&p); } } //注意这里 extern void UnitySendMessage(const char* obj, const char* method, const char* msg); void TestFunc4(int a,int b) { cout<<"[DQC]:in TestFunc4.a:"<<a<<" b:"<<b<<endl; UnitySendMessage("Main Camera","CallBackFunc4","[DQC]:success from TestFunc4"); } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
将最后一个代码片用CocoaTouchStaticLibrary工程编译成.a后,与第二个代码片的.cpp一起放到Plugins/iOS文件夹中。Unity在Build时会将Plugins复制到Xcode工程里的Libraries文件夹下。
几个注意事项:
1、尽量不要在XCode里的Libraries/Plugins中直接修改.cpp,因为很容易就被Unity覆盖或者删除了……别问我怎么知道的。如果要在XCode中修改.cpp,那么要么干脆把Unity工程里的Plugins删除,要么可以放到XCode下的Classes文件夹中(官方文档推荐的,说是不会被覆盖)。
2、官方文档说UnitySendMessage是异步的,可能会慢一帧,MonoPInvokeCallBack未知。
3、如果是在Android,可能要将dllimport中的“__Internal”改成“库文件名”。
4、[重要]CocoaTouchStaticLibrary工程的IOS deployment target要设置成和Unity Xcode工程一样,不然链接时会报错。Unity生成的Xcode默认是7.0,郁闷的是现在最低只能选8.0了,只好都改成8.0或者更高。
5、用了extern “C”后namespace就失效了(如上例TestFunc3),注意不要重定义
要是官方文档能更详细一点就好了…
相关文章推荐
- Unity3D在IOS、Android上使用C++并回调的究极解决方案
- Unity 使用C/C++ 跨平台终极解决方案(PC,iOS,Android,以及支持C/C++的平台)
- Unity 使用C/C++ 跨平台终极解决方案(PC,iOS,Android,以及支持C/C++的平台)
- 看Dropbox如何使用C++进行iOS和Android跨平台开发
- Unity3D在Android编辑模式下使用lightmap出现高亮解决方案
- Unity 使用C/C++ 跨平台终极解决方式(PC,iOS,Android,以及支持C/C++的平台)
- 看Dropbox如何使用C++进行iOS和Android跨平台开发
- [Unity3D][Vuforia][ios]使用vuforia的unity3d库在ios中摄像头只显示黑色,不显示摄像头,NO CAMERA的解决方案
- Unity3D iOS 使用 Dynamic Library 的 framework 时需要 添加 Embedded Binaries 的解决方案
- 如何使用arm-eabi-gdb调试android c/c++程序
- 如何使用arm-eabi-gdb调试android c/c++程序
- [ZZ]C++中回调(CallBack)的使用方法
- 使用GDB调试Android中的C/C++程序
- 使用android中的AIDL让Service与Activity通信(service回调activity)
- 【Cocos2d游戏开发之十二】浅析使用C++/C/OC进行iOS游戏混编出现“failed with exit”问题与小结;
- Android JNI(JNI(JAVA同C++配合使用)
- 【Cocos2d游戏开发之十二】浅析使用C++/C/OC进行iOS游戏混编出现“failed with exit”问题与小结;
- Android Jni中使用线程及回调更新UI
- 【Android游戏开发二十一】Android os设备谎言分辨率的解决方案!以及简单阐述游戏引擎如何使用!
- Android Jni中使用线程及回调更新UI