Unity 之 C#与C++/C交互指针函数指针结构体交互
1、打开Visual Studio ,新建一个工程,选择 Visual C++ 下的 Windows 桌面 下的 动态链接库(DLL),新建成工程项目,具体如下图
2、在生成的 NativeCode.h 文件中,添加要供 C# 调用的接口声明定义,具体如下图
3、NativeCode.h 的具体内容如下:#ifndef __鲍伊酷雪NativeCode_H__#define __NativeCode_H__#ifndef EX霸烹钟爷PORT_DLL#define EXPORT_DLL __declspec(dllexport) //导出dll声明#endifstruct Vector3{ float x, y, z;};struct Vector8{ int counter; float x, y, z; float a, b, c, d;};//定义一个函数指针typedef void(__stdcall *CPPCallback)(Vector8 v8);extern "C" { EXPORT_DLL void MyAddFunc(int* _a, int* _b); EXPORT_DLL void MySubFunc(int* _a); EXPORT_DLL Vector3 MyVectorFunc(Vector3 vector3); EXPORT_DLL Vector8 MyVector8Func(); //定义一个用于设置函数指针的方法,在该函数中调用C#中传递过来的委托 EXPORT_DLL void __stdcall SetCallback(CPPCallback callback); EXPORT_DLL void MyTestCallbackFunc();}#endif
4、新建一个脚本 NativaCode.cpp ,实现之前定义的接口,包括 C++与C#之间的指针交互,函数指针交互,结构体交互的接口函数,具体如下图
5、NativaCode.cpp 的具体内容如下:// NaviteCode.cpp : 定义 DLL 应用程序的导出函数。//#include "stdafx.h"#include "NaviteCode.h"int* tmp;CPPCallback callbackFunc;extern "C" { void MyAddFunc(int* _a, int* _b) { *_a = *_a + *_b; tmp = _b; } void MySubFunc(int* _a) { *_a = *_a - *tmp; } Vector3 MyVectorFunc(Vector3 vector3) { Vector3 v = vector3; v.x += 1; v.y += 2; v.z += 3; return v; } Vector8 MyVector8Func() { Vector8 v8 ={7,1,2,3,4,5,6,7}; return v8; } void __stdcall SetCallback(CPPCallback callback) { Vector8 v8 = { 7,1.1,2.2,3.3,4.4,5.5,6.6,7.7 }; //下面的代码是对C#中委托进行调用 callback(v8); callbackFunc = callback; } void MyTestCallbackFunc() { Vector8 v8 = { 7,11.1,22.2,33.3,44.4,55.5,66.6,77.7 }; callbackFunc(v8); }}
6、脚本没有错误,选中工程,右键-生成,把应用编译打包出 dll,没有失败的话,就会在目标路径生成出 dll,具体如下图
7、打开Unity,然后新建一个工程,然后在工程中,新建一个 Plugins,把之前生成的 dll 拖入进去,具体如下图
8、然后在工程中新建一个脚本 TestDLL ,引进DLL的接口函数,并与之对应构建需要的结构体(如果Unity与之对应的结构体,可使用Unity自带的),设置委托回调函数,接着对应的尝试调用的接口,并打印,便于后期查看结果,具体如下图
9、TestDLL 脚本的具体内容如下:using System.Runtime.InteropServices稆糨孝汶;using UnityEngine;[StructLayout(LayoutKind.Sequential)]public struct Vector8{ public int count; public float x, y, z; public float a, b, c, d;}public class TestDLL : MonoBehaviour{ public delegate void CSCallback(Vector8 v8); static void CSCallbackFunction(Vector8 v8) { Debug.Log("Vector8 v8: " + v8.count + " " + v8.x + " " + v8.y + " " + v8.z + " " + v8.a + " " + v8.b + " " + v8.c + " " + v8.d); } [DllImport("NaviteCode")] public static extern void MyAddFunc(ref int a, ref int b); [DllImport("NaviteCode")] public static extern void MySubFunc(ref int a); [DllImport("NaviteCode")] public static extern Vector3 MyVectorFunc(Vector3 v); [DllImport("NaviteCode")] public static extern Vector8 MyVector8Func(); [DllImport("NaviteCode")] public static extern void MyTestCallbackFunc(); [DllImport("NaviteCode")] public static extern void SetCallback(CSCallback cSCallback); // Start is called before the first frame update void Start() { int a =10; int b = 5; MyAddFunc(ref a, ref b); Debug.Log("a :"+a); int c = 20; MySubFunc(ref c); Debug.Log("c :" + c); Vector3 v = MyVectorFunc(new Vector3(1,2,3)); Debug.Log("Vector3 v :" + v); Vector8 v8 = new Vector8(); v8 = MyVector8Func(); Debug.Log("Vector8 v8: " + v8.count + " " + v8.a); SetCallback(CSCallbackFunction); MyTestCallbackFunc(); }}
10、脚本没有问题,回到Unity,场景中添加一个GameObject,并把脚本挂载上去,具体如下图
11、运行场景,即可看到,正常调用 C++封装的 DLL的接口,并且打印也符合预期,具体如下图