[Unity3D]C# 调用C++ DLL
来源:互联网 发布:unity3d 寻路插件 编辑:程序博客网 时间:2024/06/07 06:26
本文主要演示一个简单范例及介绍相关知识。
先亮出演示代码,该程序演示的是在C#代码中传入结构体与委托,然后在C++代码中调用委托并将结构体传入以进行修改。
首先C++编写的“CppDll.dll”:
typedef struct _MyStruct{ int value;}MyStruct, *PMyStruct;typedef void __stdcall ChangeValue(MyStruct *value);void __stdcall UseCallBack(MyStruct * value, ChangeValue callback){ callback(value);}
本人导出函数使用的是“模块定义文件(.def)”,建议使用这种方法,因为这样可以使在导出C++函数的时候函数名不会改变。如下:
LIBRARY CppDllEXPORTS UseCallBack @1
当然也可以使用导出符号,但是导出C++函数的时候,函数名会被修改,
所以为了方便起见,如果要使用这种方法最好导出C函数,以保证导出函数名不变,如下:
extern "C" __declspec(dllexport) ...
然后是Unity C#代码:
using UnityEngine;using System.Runtime.InteropServices;public class Test : MonoBehaviour { [StructLayout(LayoutKind.Sequential)] struct MyStruct { public int value; } [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate void ChangeValue(ref MyStruct value); [DllImport("CppDll", EntryPoint = "UseCallBack", CallingConvention = CallingConvention.StdCall)] static extern void UseCallBack(ref MyStruct value, [MarshalAs(UnmanagedType.FunctionPtr)] ChangeValue callback); [AOT.MonoPInvokeCallback(typeof(ChangeValue))] static void Change(ref MyStruct my) { my.value += 10; } void Start () { MyStruct my; my.value = 0; UseCallBack(ref my, Change); print(my.value); }}
结果:
代码亮完了,接下来详细讲解,C++代码没什么好讲,直接讲C#部分。
先讲特性部分。
StructLayout特性:允许你控制内存中类或结构的数据字段的物理布局。
- LayoutKind:控制当导出到非托管代码时对象的布局
- Sequential:对象的成员按照它们在被导出到非托管内存时出现的顺序依次布局。这些成员根据在 StructLayoutAttribute::Pack 中指定的封装进行布局,并且可以是不连续的。
- Explicit:在未管理内存中的每一个对象成员的精确位置是被显式控制的,服从于 StructLayoutAttribute::Pack 字段的设置。每个成员必须使用 FieldOffsetAttribute 指示该字段在类型中的位置。
- Auto:运行库自动为非托管内存中的对象的成员选择适当的布局。使用此枚举成员定义的对象不能在托管代码的外部公开。尝试这样做将引发异常。
一般情况下,只需要是用Sequential方式就可以了。
UnmanagedFunctionPointer特性:控制作为非托管函数指针传入或传出非托管代码的委托的调用约定。
- CallingConvention:指定调用在非托管代码中实现的方法所需的调用约定。
- Cdecl
- FastCall
- StdCall
没有什么限制,只要与C++的回调函数调用约定一致即可。
DllImport特性:使用包含要导入的方法的 DLL。
- dllName:设置导入C++ Dll的路径或相对路径。
- EntryPoint:指示要调用的 DLL 入口点的名称或序号。
- CallingConvention:上面已讲。
用于指定导入的C++ DLL和导入的函数名称和其调用约定。
MarshalAs特性:指示如何在托管代码和非托管代码之间封送数据。
根据两边的参数类型来设置,如果是都有的类型就不用设置了。
- UnmanagedType:指定如何将参数或字段封送到非托管代码。
- FunctionPtr:一个可用作 C 样式函数指针的整数。可将此成员用于 Delegate 数据类型或从 Delegate 继承的类型。
MonoPInvokeCallback特性:用于将委托声明成回调函数。
- Type:委托类型。
如果是在Unity当中必须在C# 的委托上声明,如果是在C# Console工程中就不用声明。
如上就是特性部分,特性的参数本人只列出了一部分,剩下的读者可通过对应的链接查看。
接下来,梳理下要点。
C#中的委托类型对应C++中的函数指针类型,需要声明相同的参数列表。
如果C++参数类型C#这边没有的话,则需要使用MarshalAs特性指定类型。
通过UnmanagedFunctionPointer特性使委托类型的调用约定与其相同。
C++的指针与引用对应C#的“ref”关键字。
在Unity3D中委托函数必须是静态的且必须声明MonoPInvokeCallback特性,要不然会在运行是发生异常“ExecutionEngineException: Attempting to JIT compile method ‘…’ while running with –aot-only.”。
通过DllImport导入的函数在特性参数中如果写了EntryPoint参数则函数名可以不同,否则必须相同。
导入的函数的参数类型如果C#中没有的话,则需要使用MarshalAs特性指定类型。
如有疑问请留言,欢迎一起讨论。
- [Unity3D]C# 调用C++ DLL
- C#调用C++DLL
- C#调用C++dll
- C#调用C++dll
- C#调用C++DLL
- c#调用c++DLL
- C# 调用C++dll
- C#调用C++DLL
- C#调用C++DLL
- C#调用C++DLL
- C#调用C++Dll
- C#调用C++DLL
- C#调用C、C++dll
- Unity3D教程:静态调用C#的dll
- unity3d 调用C#的dll文件
- C#调用C的DLL
- C#动态调用C++DLL
- C#调用C/C++ dll
- IO多路复用之epoll总结
- 面试之“两列布局”/ "三列布局"
- select、poll、epoll之间的区别总结[整理]
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- 图像自动标注 Automatic image annotation
- [Unity3D]C# 调用C++ DLL
- xampp设置开机启动
- centos开放8000端口
- 各个版本office卸载工具
- Mysql事项,视图,函数,触发器命令
- centos上安装及配置单台redis
- 传智播客168期JavaEE就业班(第八天 WEB简介 Tomcat)
- VS2012配置OpenCV2.4.9
- LBS-Object C 定位,地图,导航