官方链接
1.DLL的方式:
C++代码:编译成DLL,导入Unity
#pragma once
#include <map>
#include <string>
//导出宏定义
#define _DllExport _declspec(dllexport)
//函数指针
typedef void (*NativeCallback)(const char*);
extern "C"
{
//注意这里字符串不能用C++的std::string,和C#的string不等价,等价的是char*,即字符数组
_DllExport void RegisterNativeCallback(const char* functionName, NativeCallback callback);
_DllExport void UpdateNative();
}
//缓存C#函数的地址
std::map<std::string, NativeCallback> _callbackMap;
//导出让C#调用,注册C#端的函数,注册后就可以在C++端调用C#的函数,本质就职把C#函数的地址给到C++,C++调用。
_DllExport void RegisterNativeCallback(const char* functionName, NativeCallback callback)
{
_callbackMap[std::string(functionName)] = callback;
}
//导出让C#调用
_DllExport void UpdateNative()
{
//调用C#端的函数,可以在Unity性能分析界面看到Native update,用此方法可以在Unity界面查看C++代码的耗时
_callbackMap[std::string("BeginSample")]("Native update");
_callbackMap[std::string("Log")]("Native Log");
_callbackMap[std::string("EndSample")]("Native update");
}
C#代码:
using AOT;
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Profiling;
namespace Haha
{
public class TestCPPLib : MonoBehaviour
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void NativeCallback(string args);
[DllImport("CPPLib")]
static extern void RegisterNativeCallback(string functionName, IntPtr callback);
[DllImport("CPPLib")]
static extern void UpdateNative();
[MonoPInvokeCallback(typeof(NativeCallback))]
static void CallbackLog(string args)
{
Debug.Log(args);
}
[MonoPInvokeCallback(typeof(NativeCallback))]
static void CallbackBeginSample(string args)
{
Profiler.BeginSample(args);
}
[MonoPInvokeCallback(typeof(NativeCallback))]
static void CallbackEndSample(string args)
{
Profiler.EndSample();
}
void Start()
{
//调用C++函数,注册C#函数
RegisterNativeCallback("Log", Marshal.GetFunctionPointerForDelegate(new NativeCallback(CallbackLog)));
RegisterNativeCallback("BeginSample", Marshal.GetFunctionPointerForDelegate(new NativeCallback(CallbackBeginSample)));
RegisterNativeCallback("EndSample", Marshal.GetFunctionPointerForDelegate(new NativeCallback(CallbackEndSample)));
}
private void Update()
{
//调用C++函数
UpdateNative();
}
}
}
2.还有一种是C++源码作为插件,只支持il2cpp。
C++代码:直接放到Unity的Assets目录下
C#源文件:区别只在导入时不写具体的文件名,写:__Internal即可,因为用IL2CPP 后端的方式,会把C++源文件放到工程内部一块编译。
using AOT;
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Profiling;
namespace Haha
{
public class TestCPPLib : MonoBehaviour
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void NativeCallback(string args);
//区别在这里:
[DllImport("__Internal")]
static extern void RegisterNativeCallback(string functionName, IntPtr callback);
[DllImport("__Internal")]
static extern void UpdateNative();
[MonoPInvokeCallback(typeof(NativeCallback))]
static void CallbackLog(string args)
{
Debug.Log(args);
}
[MonoPInvokeCallback(typeof(NativeCallback))]
static void CallbackBeginSample(string args)
{
Profiler.BeginSample(args);
}
[MonoPInvokeCallback(typeof(NativeCallback))]
static void CallbackEndSample(string args)
{
Profiler.EndSample();
}
void Start()
{
RegisterNativeCallback("Log", Marshal.GetFunctionPointerForDelegate(new NativeCallback(CallbackLog)));
RegisterNativeCallback("BeginSample", Marshal.GetFunctionPointerForDelegate(new NativeCallback(CallbackBeginSample)));
RegisterNativeCallback("EndSample", Marshal.GetFunctionPointerForDelegate(new NativeCallback(CallbackEndSample)));
}
private void Update()
{
UpdateNative();
}
}
}
如果只是查看C++代码的耗时,unity提供了C++的接口,更加方便,视频最后有介绍。
Unity官方手册有具体代码
关于IL2CPP打包的测试:
1.直接通过Unity构建,结构如下:如下:大小313M
2.通过创建VS解决方案(可以在VS里设置断点,修改调试C++代码),在VS里构建,在构建界面设置:
结构如下:bin目录包含软件的data目录,具体生成的exe在各自的平台下:
最终把bin目录的data文件夹和对应平台的exe何在一起,如下:大小162M
上面的lib、pdb、exp可以删除,测试不影响运行,精简后的目录:大小50.8M
结论:用vs构建的体积更小。