Unity调用C++ DLL传递自定义类型

Unity在类型定义时,使用class会导致Unity闪退

//注意这里不能使用class,只能使用struct
    [StructLayout(LayoutKind.Sequential)]
    public struct Touch
    {
        public int id;
        public float x, y;
        public float time;
    }

Unity调用:

    [DllImport(DllName)]
    private static extern Touch testTouch(Touch touch);

C++ dll类型定义

	//这里可以使用class,C++的class与struct没太大区别
	class Touch
	{
	public:
		int id;
		float x, y;
		int state;
		double time;
		Touch(int _id, float _x, float _y, int _type, double _time)
			:id(_id), x(_x), y(_y), state(_type), time(_time)
		{
		}
		Touch()
			:id(0), x(0), y(0), state(0), time(0)
		{
		}
	};

C++ 函数定义:

    __declspec(dllexport) Touch testTouch(Touch touch)
    {
        //测试,Unity的类实例作为函数参数,进行处理
        Touch nt;
        nt.id = touch.id + 100;
        nt.state = touch.state + 100;
        nt.time = touch.time + 100;
        nt.x = touch.x + 100;
        nt.y = touch.y + 100;
        return nt;
    }

在与C++相互传递类型时,Unity中,不能使用class来定义类型,只能使用struct,否则会造成Unity闪退。

原因分析:内存布局的一致性

  • C++
    • 在 C++ 中,结构体和类的内存布局是确定的,特别是在不包含虚函数的情况下。结构体和类的字段是按声明顺序紧凑排列的(除非有特殊的对齐要求)。
  • C#
    • C# 的 struct 是值类型,内存布局与 C++ 的结构体非常相似。它们的字段在内存中是按顺序排列的,没有额外的间接层。
    • C# 的 class 是引用类型,包含一个指向堆上对象的指针。这意味着引用类型在内存中有一个额外的间接层,与 C++ 的内存布局不一致。

C++内存布局示意图:

------------------------------------------
|   id    |    x    |    y    |   time  |
------------------------------------------
| 4 bytes | 4 bytes | 4 bytes | 8 bytes |
------------------------------------------

C#内存布局示意图:

struct:
---------------------------------------------------------
|   id    |    x    |    y    |   time  |
---------------------------------------------------------
| 4 bytes | 4 bytes | 4 bytes | 8 bytes |
---------------------------------------------------------




class:

栈:
--------------
| ptr | --->堆
--------------

堆:
---------------------------------------------------------
|   id    |    x    |    y    |   time  |
---------------------------------------------------------
| 4 bytes | 4 bytes | 4 bytes | 8 bytes |
---------------------------------------------------------

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将C++代码打包给Unity调用,可以通过以下步骤: 1. 创建一个C++库项目,并将其编译为DLL文件。 2. 在Unity中创建一个C#脚本,使用DllImport特性引用DLL文件中的函数。 3. 在C#脚本中调用DLL函数。 下面是一个简单的示例: 1. 创建C++库项目,并将其编译为DLL文件。 首先,创建一个C++库项目并实现一些函数。例如,下面是一个简单的Add函数,它将两个整数相加并返回结果: ``` // MyMathLib.h #ifdef MYMATHLIB_EXPORTS #define MYMATHLIB_API __declspec(dllexport) #else #define MYMATHLIB_API __declspec(dllimport) #endif extern "C" MYMATHLIB_API int Add(int a, int b); ``` ``` // MyMathLib.cpp #include "MyMathLib.h" int Add(int a, int b) { return a + b; } ``` 在这里,我们使用了`__declspec(dllexport)`和`__declspec(dllimport)`来指示编译器导出和导入DLL函数。`MYMATHLIB_API`宏用于将函数标记为导出或导入。 2. 在Unity中创建一个C#脚本,使用DllImport特性引用DLL文件中的函数。 在Unity中,我们可以创建一个C#脚本,并使用DllImport特性来引用DLL文件中的函数。例如,下面是一个简单的例子: ``` // MyMathLib.cs using System.Runtime.InteropServices; public static class MyMathLib { [DllImport("MyMathLib.dll")] public static extern int Add(int a, int b); } ``` 在这里,我们使用DllImport特性来引用DLL文件中的Add函数。`"MyMathLib.dll"`是DLL文件的名称。 3. 在C#脚本中调用DLL函数。 现在,我们可以在C#脚本中调用DLL函数。例如,下面是一个简单的测试: ``` // Test.cs using UnityEngine; public class Test : MonoBehaviour { void Start() { int result = MyMathLib.Add(2, 3); Debug.Log("Result: " + result); // Output: Result: 5 } } ``` 在这里,我们使用`MyMathLib.Add`来调用DLL文件中的Add函数,并将结果打印到Unity控制台中。 这就是将C++代码打包给Unity调用的基本步骤。当然,具体实现可能因项目而异。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值