C++ 之动态链接库DLL使用注意事项及C#调用详解

C++ 之动态链接库DLL使用注意事项及C#调用详解

  • 有时候算法开发完成之后需要封装成动态链接库DLL来进行集成,一方面增加了算法or代码的复用或者广泛使用性,另一方面也起了保密的效果
  • 平时封装成DLL之后放到一台新的电脑上会出现问题,所以本文总结一下其中问题及解决方式
  • C#调用DLL这个和C++也有不同之处,至于详细解释,后边慢慢增加
  • 关于C++ 与 C# 之间的数据对应关系,可以参考我的另一篇文章:https://blog.csdn.net/yohnyang/article/details/128355275

1. DLL封装

1.1 封装

  • 当C++开发好了code后,封装可以有两种方式:

      1. VS中新建DLL项目,可以将开发的code复制到新项目中,编译生成DLL。一般新建一个DLL项目后,会自动生成如下几个文件:
cpp 复制代码
//**************************************************************************************************
//framework.h
#pragma once

#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>

//**************************************************************************************************
// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。
#ifndef PCH_H
#define PCH_H

// 添加要在此处预编译的标头
#include "framework.h"
#endif //PCH_H

//**************************************************************************************************
// pch.cpp: 与预编译标头对应的源文件

#include "pch.h"
#include<iostream>

// 当使用预编译的头时,需要使用此源文件,编译才能成功。

//**************************************************************************************************
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

将想要封装的code填充到pch中:

cpp 复制代码
// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。
#ifndef PCH_H
#define PCH_H

// 添加要在此处预编译的标头
#include "framework.h"

extern "C" _declspec(dllexport) int test1(int a, float* output);

#endif //PCH_H

//***********************************************************************************************
// pch.cpp: 与预编译标头对应的源文件

#include "pch.h"
#include<iostream>

// 当使用预编译的头时,需要使用此源文件,编译才能成功。

int test1(int a, float* output)
{
	output[0] = a;
	printf("test1 ok....");
	return 1;
}
  • 另一种封装方式就是直接在C++项目中包含常用头文件,然后将输出文件有.exe改为.dll,其他属性酌情修改~
cpp 复制代码
#inlcude<Windows.h>

1.2 查询DLL依赖

  • 打开VS2019目录下自带的命令行窗口,输入命令dumpbin /dependents xx.dll 查询即可:

  • 如果调用时无法打开,可以先查询一下依赖,然后在编译电脑中找出相关的.dll复制到目标路径下即可,一般是在C:/ 盘路径下的C:\Windows\System32 文件夹中及环境变量路径下进行 search

    • C++ 调用.dll打不开时会有提示缺少哪个
    • C# 调用.dll打不开时只会提示无法找到.dll

2. 调用

2.1 C++ 调用

  • 新建VS项目,右键项目名称添加新建项 test_0.cpp,编写测试code:
cpp 复制代码
/*
* 测试dll
*/
#include <iostream>
#include <Windows.h>

int main()
{
    typedef int(*testFunc)();
    HMODULE module = LoadLibrary(L".\\Dll1.dll");
    if (module == NULL)
    {
        std::cout << "加载DemoDLL.dll动态库失败\n" << std::endl;
        return -1;
    }
    else {
        std::cout << "加载成功...\n";
    }

    testFunc test1 = (testFunc)GetProcAddress(module, "test1");
    test1();

    return 1;
}

2.2 C# 调用

  • 新建VS 中C#空项目,将Dll1.dll放到 .\bin\x64\Release 目录下,然后 coding ex:
csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApp1
{
    class Program
    {
        public class ABC
        {
            [DllImport(@"Dll1.dll", EntryPoint = "test1", CharSet = CharSet.Auto, ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
            public static extern int test1(int a, float[] output);

        }

        static void Main(string[] args)
        {
            float[] data = new float[10];
            ABC.test1(3,data);
            Console.ReadLine();
        }
    }
}
相关推荐
Algorithm15763 分钟前
云原生相关的 Go 语言工程师技术路线(含博客网址导航)
开发语言·云原生·golang
shinelord明13 分钟前
【再谈设计模式】享元模式~对象共享的优化妙手
开发语言·数据结构·算法·设计模式·软件工程
呆呆小雅18 分钟前
C#关键字volatile
java·redis·c#
Monly2119 分钟前
Java(若依):修改Tomcat的版本
java·开发语言·tomcat
boligongzhu20 分钟前
DALSA工业相机SDK二次开发(图像采集及保存)C#版
开发语言·c#·dalsa
Eric.Lee202120 分钟前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频
小俊俊的博客21 分钟前
海康RGBD相机使用C++和Opencv采集图像记录
c++·opencv·海康·rgbd相机
7yewh23 分钟前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux
waicsdn_haha34 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
嵌入式科普35 分钟前
十三、从0开始卷出一个新项目之瑞萨RZN2L串口DMA接收不定长
c语言·stm32·瑞萨·e2studio·rzn2l