C#调用C++Dll库小示例

C#调用C++Dll库小示例

先巩固复习语言的分类:Program Errors(程序错误)

  • trapped errors:导致程序终止执行(程序意识到出错,使用对应的错误处理机制),如除 0,Java 中数组越界访问
  • untrapped errors:程序出错后继续执行(其实并不一定保证继续执行,程序本身并不知道出错,也没有对应的错误处理机制),如 C 语言里的缓冲区溢出,Jmp 到错误地址

Forbidden Behaviors(禁止行为)

程序在设计的时候会定义一组 forbidden behaviors,包括了所有的 untrapped errors,可能包括 trapped errors。

Well behaved、ill behaved

  • well behaved: 如果程序的执行不可能出现 forbidden behaviors,则称为 well behaved

  • ill behaved: 只要有可能出现 forbidden behaviors,则称为 ill behaved

  • img

从图中可以看出,绿色的 program 表示所有程序(所有程序,你能想到和不能想到的),error 表示出错的程序,error 不仅仅包括 trapped error 和 untrapped error。

根据图我们可以严格的定义动态类型,静态类型;强类型,弱类型

  • 强类型:如果一门语言写出来的程序在红色矩形外部,则这门语言是强类型的,也就是上面说的 well behaved
  • 弱类型:如果一门语言写出来的程序可能在红色矩形内部,则这门语言是弱类型的,也就是上面说的 ill behaved
  • 静态类型:一门语言在编译时排除可能出现在红色矩形内的情况(通过语法报错),则这门语言是静态类型
  • 动态类型:一门语言在运行时排除可能出现在红色矩形内的情况(通过运行时报错,但如果是弱类型可能会触发 untrapped error,比如隐式转换,使得程序看起来似乎是正常运行的),则这门语言是动态类型

编写可被C#调用的C++动态链接库:

.h文件

#ifndef __CppDynamic__
#define __CppDynamic__
extern "C" __declspec(dllexport) int __stdcall Max(int a, int b, int c);
#endif

.cpp文件

#include "CppDynamic.h"

__declspec(dllexport) int __stdcall Max(int a, int b, int c)
{
	int tmp = a > b ? a: b;
	return tmp > c ? tmp : c;
}

关键词解析:
1.extern "C"
主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言(而不是C++)的方式进行编译。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。

2.__declspec
declspec用于指定所给定类型的实例的与Microsoft相关的存储方式。其它的有关存储方式的修饰符如static与extern等是C和 C++语言的ANSI规范,而declspec是一种扩展属性的定义。扩展属性语法简化并标准化了C和C++语言关于Microsoft的扩展。

3.dllexport
用于dll导出函数

4.__stdcall
标准调用方式

生成dll(根据版本生成不同版本的dll)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1NU3OD5C-1638541340561)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211203215703664.png)]

从Debug文件夹将Dll文件和pdb文件导入unity中(并设置相关平台)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gDlVtQWl-1638541340564)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211203221300870.png)]

C#代码:

using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using UnityEngine;
using Debug = UnityEngine.Debug;
//定义对应的函数名调用dll接口
public class CppTest
{
    [DllImport("CppDynamic")]
    public static extern int Max(int a, int b, int c);
}
public class CppTestter : MonoBehaviour
{
    void Start()
    {
        Debug.Log(CppTest.Max(1, 2, 3));
    }

    int MaxCS(int a, int b, int c)
    {
        int tmp = a > b ? a : b;
        return tmp > c ? tmp : c;
    }
//效率测试
    public void Test()
    {
        Stopwatch sw = new Stopwatch();
        for (int i = 0; i < 1000000; i++)
        {
            sw.Start();
            MaxCS(1, 2, 3);
            sw.Stop();
        }
        Debug.Log(sw.ElapsedMilliseconds);
        
        sw.Reset();
        for (int i = 0; i < 1000000; i++)
        {
            sw.Start();
            CppTest.Max(1, 2, 3);
            sw.Stop();
        }
        Debug.Log(sw.ElapsedMilliseconds);
    }
    
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UjvqY0AH-1638541340565)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211203221712670.png)]
效率测试:
在这里插入图片描述
在编辑旗下,调用C++库所耗费的时间是比C#代码时间长很多的!!!

猜你喜欢

转载自blog.csdn.net/weixin_43381316/article/details/121708305
今日推荐