Visual Studio中C++文件打包为.dll文件,并调用(C++&Unity C#)

一、C++打包为DLL文件

1、创建dll项目

在这里插入图片描述

2、新建头文件(.h)和源文件(.cpp)

新建后项目中会自动生成4个文件,可以删除新建,也可以使用其中的pch.xx。
在这里插入图片描述

3、更改头文件和源文件内容

(1)源文件(pch.cpp)
同运行要打包的C++文件,先添加需要调用的文件,然后添加要打包的方法函数。

#include "pch.h"
#include<iostream>
#include<string>
int add(int a, int b, const std::string& func)
{
	std::string str = func;
	return a + b;
}

(2)头文件(pch.h)

#include<iostream>

#ifdef MY_DLL_API
#else
#define MY_DLL_API extern "C" _declspec(dllimport)
// extern "C" 以C的方式导出,保证了接口名称不变
#endif

MY_DLL_API int add(int a, int b, const std::string& func);

4、生成DLL文件

在这里插入图片描述
在…\x64\Debug文件夹下生成项目名同名的4个文件,我们使用xx.dll,xx.lib:
在这里插入图片描述

二、C++ 调用DLL文件

1、显式调用

可以仅使用.dll文件即可完成调用。
(1)LoadLibrary() 加载dll并返回一个句柄,可以是HMODULE或者HINSTANCE(HINSTANCE在win32下与HMODULE是相同的东西,在Win32下还存在主要是因为win16)
(2)用GetProcAddress()获得DLL文件中函数的的地址,(函数的入口点)之后就可以调用dll中的函数了
(3)要用FreeLibrary(HMODULE)卸载dll

优点:可以决定何时记载和卸载dll,充分体现DLL的灵活性。
缺点:调用繁琐。

#include <iostream>
#include <Windows.h>  

typedef int (*MYDLLFUNCTION)(int a, int b, const std::string& filename);

int main() {

    HINSTANCE hInstLibrary = LoadLibrary(L".../.../cropimage.dll");

    if (hInstLibrary) {
        MYDLLFUNCTION func_add= (MYDLLFUNCTION)GetProcAddress(hInstLibrary, "add");
        if (func_add) {
            std::string path = "add加法";
            func_add(1, 2, path); // 调用函数 
        }
        FreeLibrary(hInstLibrary); // 释放DLL  
        return 0;
    }
}

2、隐式调用

需要.lib链接到.dll文件,完成调用。
(1)读入DLL对应的cropimage.lib文件
(2)dllimport导出dll里面的函数

#include <iostream>
#pragma comment(lib, ".../.../cropimage.lib")

extern "C" _declspec(dllimport) int add(int a, int b, const std::string& func);;
//要有extern "C" 和原先定义的一致,否则会报错

int main()
{
	std::string path = "add加法";
	add(1, 2, path);
}

三、在Unity中使用C#调用DLL文件

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;

public class test_dll : MonoBehaviour
{
    [DllImport("RoiDllCallForUnity", CallingConvention = CallingConvention.StdCall)]
    public static extern void cropImageROI(int a, int b, string func);
    
    // Start is called before the first frame update
    void Start()
    {
    	string path = "add_加法";
        int sum = add(1, 2, path);
    }
    
    // Update is called once per frame
    void Update()
    {
    }
}

注意!!!
【问题】在unity中调用时出现问题:在A电脑生成的.dll文件可以在A电脑上调用,在B电脑上无法正常调用(报错:DllNotFoundException: RoiDllCallForUnity assembly: type: member:(null) test_dll.Start () (at Assets/test_dll.cs:19))。同样,B电脑上生成的.dll文件无法在A电脑上调用。
【原因】这个dll编译时依赖其他库,运行时也需要依赖其他动态库,而打包移植时没有拷贝所依赖的这些库。
我就是因为不同电脑opencv版本不同,opencv_worldxxxd.dll文件不同,而自己电脑上是配置路径可以读取的。
【解决方法】搞清楚所有依赖项,移植时全部拷贝。
1.用Dependency Walker 2.2(打开DependenciesGui.exe并拖入*.dll)或其他dll查看器打开*.dll
2.查看该电脑缺失(显示红色的)的*.dll的依赖库并下载,比如dll中调用了CGAL库,新电脑上缺失相关依赖库,则需要下载如下dll
3.把缺失依赖库同样放到Unity项目的Assets-Plugins中。在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值