Windows下Dll在Unity中使用的一般方式

Windows下Dll在Unity中使用的一般方式

Unity中虽然已经有广泛的库和插件,但是相较于C++的库生态而言,还是有一定的差距;因此本篇博文记录Windows下将C++函数打包成动态链接库在Unity中使用的一般方法。

环境

Visual Studio 2019 , Unity2022 , Windows11,OpenCV

说明

  1. Unity中有针对Windows 下DLL文件的自动加载机制,所以只要把打包好的动态链接库拷贝到 Assets/Plugins,然后在Unity脚本中进行注册便可以使用。
  2. 由于动态链接库本质上可以理解成一个插件,所以本次记录侧重 Unity和C++动态链接库函数的传参一致性问题

步骤

Visual Studio 2019

  1. 新建一个项目,在源文件中按照如下格式编写函数

​ 缩略版:

extern "C" {

	// 变量
    static bool isModelInitialized = false;

    __declspec(dllexport) int add( int width, int height) {
        return width + height;
    }

}

​ Demo:

#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
//#include"opencv2/xfeatures2d.hpp"
#include "SFace.h"
#include "opencv2/dnn.hpp"
#include "opencv2/calib3d.hpp"
#include "opencv2/video.hpp"
#include "face_detector.hpp"
#include <iostream>


using namespace cv;
using namespace declass;

extern "C" {

	// 
    static bool isModelInitialized = false;
    static YOLOv8_face* fdModel = nullptr;
    static SFace* face_recognizer = nullptr;
    static Mat targetFeature;

    __declspec(dllexport) bool reGetStartFaceBox(unsigned char* pixelData, int width, int height, int* box) {

        return false;
    }

    __declspec(dllexport) bool getStartFaceFeature(unsigned char* pixelData, int width, int height) {
        return true;
    }

    // 释放资源的函数
    __declspec(dllexport) void Cleanup() {
     {
        delete fdModel;
        delete face_recognizer;
        fdModel = nullptr;
        face_recognizer = nullptr;
        isModelInitialized = false;
       
    }

extern "C" 是一种 C++ 中的语言链接约定,用于指示编译器以 C 的方式处理函数的名称修饰(name mangling)规则。

__declspec(dllexport) 是 Microsoft 编译器特有的一个声明符,用于声明某个函数、变量或类在 DLL(动态链接库)中导出,使得它可以被其他程序或库调用。

image-20250111170515174

之后进行编译,便可以得到一个dll文件。

Unity

接下来需要将动态链接库拷贝到Unity的Assets/Plugins目录:

image-20250111170709616

接下来我们新建一个脚本,在Unity中注册我们编写好的函数

public class FaceRecongnize
{
    // faceRecong是dll文件名字,函数名和上面的demo是一致的。
    [DllImport("faceRecong", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    public static extern bool reGetStartFaceBox(IntPtr pixelData, int width, int height, int[] box);

    [DllImport("faceRecong", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    public static extern bool getStartFaceFeature(IntPtr pixelData, int width, int height);

    [DllImport("faceRecong", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    public static extern void Cleanup();

}

至于参数,比如我想把一个纹理,或者一个数组传入到动态链接库中进行赋值,一般是用指针进行传送,比如上面的纹理数据和box,都是指针。

调用示例。

image-20250111171259391

PS:一个比较值得关注的点是,如果使用了第三方库,OpenCV,我们还需要把OpenCV相关的dll文件也拷贝到Assets/Plugins下,这是因为动态链接库之间也有一些依赖关系,我们需要把他们都导入进去。同时我建议如果要打包的话,因为可能跨设备运行,所以建议采用相对目录的方式,配置Visual Studio中的第三方库的依赖关系。

Refer

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王行知

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值