Unity3D中调用C++动态链接库(dll)-两种方式(Managed Plugins 和 Native Plugins)

问题描述

在Unity3d脚本中实现对C++动态库的调用。假设需要在脚本中调用dll里面的一个函数,函数名下:

int PathPlanning(INPUT *input, OUTPUT *output); //其中INPUT 和 OUTPUT 是自定义的结构体(或者类,一样的)

简单介绍一下这个函数:

这是用于机器人路径规划的一个函数,传给它一个INPUT结构体(里面是一些输入参数),它返回给我一个OUTPUT结构体(我们所需要的输出)。函数的int返回值代表路径规划是否成功。

unity中调用动态链接库的两种方式

根据官方文档https://docs.unity3d.com/Manual/Plugins.html,unity可以对两种dll进行调用——Managed Plugins和Native Plugins。一种是托管代码编译的dll,一种是非托管代码编译的dll。


所以我们可以有两种思路:1是用CLR对再封装一层,使之成为托管代码,然后调用CLR编译出的dll。2是在unity3D中直接调用c++的dll。这二者有什么区别呢?

第二种方式只能调用C++dll中的函数,不能使用它里面的类。第一种方式即可使用函数和类,然而,如果C++代码中有指针,编译出的CLR只能是unsafe的,在Unity3D 2018.1之前的版本并不支持。

所以,我们只能用二种方式——直接在Unity3D中调用C++的dll。


unity中调用C++的dll

c++的头文件如下:

extern "C" {
	typedef struct PathPlanInputForUnity{
		int PlanMode;               
		double PlanStep;			
		double Acc_des;             
		double Vel_max;             
		int PlanJoint;              
		double Joint_ini[6];			
		double Joint_des[6];			
		double PEend_mid[6];        
		double PEend_des[6];        
	}INPUT;

	typedef struct PathPlanOutputForUnity{
		int totalstep;					  
		double plantime;				  
		double ResultJointVel[20000];      
		double ResultJoint[20000];         
		double endPE[20000];               
	}OUTPUT;
}

extern "C" _declspec(dllexport) int _stdcall PathPlanning(INPUT *input, OUTPUT *output);

extern "C"是为了让编译器按照C语言的方式编译dll,_stdcall定义调用方式。

在unity中调用:

//定义INPUT和OUTPUT结构体
[StructLayout(LayoutKind.Sequential)]
    struct INPUT
    {
        public int PlanMode;               
        public double PlanStep;            
        public double Acc_des;             
        public double Vel_max;             
        public int PlanJoint;              
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
        public double[] Joint_ini;         
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
        public double[] Joint_des;         
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
        public double[] PEend_mid;         
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
        public double[] PEend_des;         
    };

    [StructLayout(LayoutKind.Sequential)]
    struct OUTPUT
    {
        public int totalstep;                   
        public double plantime;                  
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20000)]
        public double[] ResultJointVel;      
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20000)]
        public double[] ResultJoint;        
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20000)]
        public double[] endPE;               
    };
//引入dll中的函数
[DllImport("PathPlanningCplus", EntryPoint = "PathPlanning", CallingConvention = CallingConvention.StdCall)]
    private static extern int PathPlanning(IntPtr pv1, IntPtr pv2);

下面调用上面声明的int PathPlanning(IntPtr pv1, IntPtr pv2)函数。其中IntPtr是通用平台指针,结构体必须转换为IntPtr才能作为参数传递给函数。

void Start () {

        //INPUT对象
        INPUT pIn = new INPUT();
        pIn.PlanMode = 1;
        pIn.PlanStep = 50;
        pIn.Acc_des = 0.01;
        pIn.Vel_max = 0.05;
        pIn.Joint_ini = new double[6] { 10, -16, 45, 112, 23, 30 };
        pIn.Joint_des = new double[6] { 58, 50, 45, 112, 23, 54 };
        pIn.PEend_des = new double[6] { 3.5, 6, 3, -80, -76, -90 };


        //把INPUT对象转换为IntPtr(即托管内存转换为非托管内存)
        int sizeIn = Marshal.SizeOf(typeof(INPUT));
        IntPtr pBuffIn = Marshal.AllocHGlobal(sizeIn);
        Marshal.StructureToPtr(pIn, pBuffIn, true);

        //给OUTPUT分配非托管内存
        int sizeOut = Marshal.SizeOf(typeof(OUTPUT));
        IntPtr pBuffOut = Marshal.AllocHGlobal(sizeOut);

        //调用路径规划函数
        int result2 = PathPlanningStartWorking(pBuffIn, pBuffOut);

        //将OUTPUT的非托管内存转换为托管内存
        OUTPUT pOut = (OUTPUT)Marshal.PtrToStructure(pBuffOut, typeof(OUTPUT)); //得到了我们所需要的pOut
    }

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值