官方链接
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官方手册
//使用这两个原生接口,需要在C++项目属性配置:VC++目录->包含目录 或 C/C++->常规->附加包含目录,添加Unity这两个文件的文件路径
#include <IUnityInterface.h>
#include <IUnityProfiler.h>
static IUnityProfiler* s_UnityProfiler = NULL;
static const UnityProfilerMarkerDesc* s_MyPluginMarker = NULL;
static bool s_IsDevelopmentBuild = false;
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces * unityInterfaces)
{
s_UnityProfiler = unityInterfaces->Get<IUnityProfiler>();
if (s_UnityProfiler == NULL)
return;
s_IsDevelopmentBuild = s_UnityProfiler->IsAvailable() != 0;
s_UnityProfiler->CreateMarker(&s_MyPluginMarker, "MyCustomMethod", kUnityProfilerCategoryOther, kUnityProfilerMarkerFlagDefault, 0);
}
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload()
{
s_UnityProfiler = NULL;
}
extern "C" void UNITY_INTERFACE_EXPORT InterfaceUpdate()
{
if (s_IsDevelopmentBuild)
{
s_UnityProfiler->BeginSample(s_MyPluginMarker);
}
//测试耗时代码
for (int i = 0; i < 100000; i++)
{
}
if (s_IsDevelopmentBuild)
{
s_UnityProfiler->EndSample(s_MyPluginMarker);
}
}
关于IL2CPP打包的测试:
1.直接通过Unity构建,结构如下:如下:大小313M
2.通过创建VS解决方案(可以在VS里设置断点,修改调试C++代码),在VS里构建,在构建界面设置:
结构如下:bin目录包含软件的data目录,具体生成的exe在各自的平台下:
文章来源:https://www.toymoban.com/news/detail-524105.html
最终把bin目录的data文件夹和对应平台的exe何在一起,如下:大小162M
上面的lib、pdb、exp可以删除,测试不影响运行,精简后的目录:大小50.8M
结论:用vs构建的体积更小。文章来源地址https://www.toymoban.com/news/detail-524105.html
到了这里,关于Unity Native Plugin C#和C++互相调用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!