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

news2025/1/22 9:01:36

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项目后,会自动生成如下几个文件:
        在这里插入图片描述
//**************************************************************************************************
//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中:

// 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,其他属性酌情修改~
#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:
    在这里插入图片描述
/*
* 测试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:
    在这里插入图片描述
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();
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/883628.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

企事业数字培训及知识库平台

前言 随着信息化的进一步推进&#xff0c;目前各行各业都在进行数字化转型&#xff0c;本人从事过医疗、政务等系统的研发&#xff0c;和客户深入交流过日常办公中“知识”的重要性&#xff0c;再加上现在倡导的互联互通、数据安全、无纸化办公等概念&#xff0c;所以无论是企业…

Gitlab-第四天-CD到k8s集群的坑

一、.gitlab-ci.yml #CD到k8s集群的 stages: - deploy-test build-image-deploy-test: stage: deploy-test image: bitnami/kubectl:latest # 使用一个包含 kubectl 工具的镜像 tags: - k8s script: - ls -al - kubectl apply -f deployment.yaml # 根据实际情况替换…

UDS (Unified Diagnostic Services)汽车诊断标准协议

作者博客主页 作者 : Eterlove 一笔一画&#xff0c;记录我的学习生活&#xff01;站在巨人的肩上Standing on Shoulders of Giants! 该文章为原创&#xff0c;转载请注明出处和作者 参考文献&#xff1a; 《道路车辆统一诊断服务(UDS) Road vehicles - Unified diagnostic s…

【Windows 常用工具系列 8 -- 修改鼠标光标(指针)大小和颜色的快速方法方法】

文章目录 修改方法 上篇文章&#xff1a;Windows 常用工具系列 7 – 禁用win10自带的微软输入法 修改方法 Win键 i 快捷键进入设置页面&#xff0c;然后输入光标... 就会跳出修改鼠标大小与光标颜色的选项。 Win键是在计算机键盘左下角Ctrl和Alt键之间的按键 根据自己的需求…

强训第32

选择 D B A A 发送TCP意思应该是已经建立了连接&#xff0c;会超时重传。在未建立连接的时候&#xff0c;会放弃该链接 C A 80端口是http A 交换机攻击主要有五种&#xff1a;VLAN跳跃攻击 生成树攻击 MAC表洪水攻击 ARP攻击 VTP攻击 B A 2^(32-26)2^(32-27)2^(32-27)128 减去…

6.3 社会工程学攻击

数据参考&#xff1a;CISP官方 目录 社会工程学攻击概念社会工程学攻击利用的人性 “弱点”典型社会工程学攻击方式社会工程学攻击防护 一、社会工程学攻击概念 什么是社会工程学攻击 也被称为 "社交工程学" 攻击利用人性弱点 (本能反应、贪婪、易于信任等) 进…

你永远想象不到有多折磨的 Android 开发 react-native gradle*!¥%#

很难过&#xff0c;拿到项目运行不起来&#xff0c;错误报告研究几天没研究明白&#xff0c;改代码&#xff0c;装gradle&#xff0c;忙和好久还是一个样&#xff0c;也不知道是码的问题还是什么&#xff0c;一开始 后面装完gradle&#xff0c;不报错了&#xff0c;但是也跑不起…

leetcode 力扣刷题哈希表初尝试

哈希表 刷题初尝试 哈希表基础知识242. 有效的字母异位词383. 赎金信49. 字母异位词分组438. 找到字符串中所有字母异位词 哈希表基础知识 哈希表是一种数据结构&#xff0c;也叫散列表。哈希表中存储的是键值对&#xff0c;即(key&#xff0c;value)&#xff0c;根据key直接查…

draw.io导出矢量图到word报错text is not svg - cannot display

先参考https://blog.csdn.net/a625750076/article/details/126384831 如果不行&#xff0c;可能是转存的问题 解决方法&#xff1a;直接在draw.io上操作 第一步 第二步 然后再word中粘贴&#xff0c;依旧是矢量图哦&#xff01;

LeetCode150道面试经典题-- 汇总区间(简单)

1.题目 给定一个 无重复元素 的 有序 整数数组 nums 。 返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说&#xff0c;nums 的每个元素都恰好被某个区间范围所覆盖&#xff0c;并且不存在属于某个范围但不属于 nums 的数字 x 。 列表中的每个区间范围 [a,…

Wi-Fi 安全在学校中的重要性

Wi-Fi 是教育机构的基础设施&#xff0c;从在线家庭作业门户到虚拟教师会议&#xff0c;应有尽有。大多数 K-12 管理员对自己的 Wi-Fi 网络的安全性充满信心&#xff0c;并认为他们现有的网络安全措施已经足够。 不幸的是&#xff0c;这种信心往往是错误的。Wi-Fi 安全虽然经常…

Excel设置某列或者某行不某行不可以编辑,只读属性

设置单元格只读的三种方式: 1、通过单元格只读按钮&#xff0c;设置为只为 设置行或者列的只读属性&#xff0c;可以设置整行或者整列只读 2、设置单元格编辑控件为标签控件(标签控件不可编辑) 3、通过锁定行&#xff0c;锁定行的修改。锁定的行与只读行的区别在于锁定的行不…

docker-compose部署nacos 2.2.3

1、编写docker-compose.yml文件 version: "3.1" services:nacos:restart: alwaysimage: nacos/nacos-server:v2.2.3container_name: nacosenvironment:- NACOS_AUTH_ENABLEtrue- MODEstandalone- NACOS_AUTH_TOKEN8b92c609089f74db3c5ee04bd7d4d89e8b92c609089f74db…

高层建筑全景vr火灾隐患排查模拟培训软件助力群众防范火灾伤害

随着城市化进程的加快&#xff0c;楼宇建筑的数量也在不断增加。然而&#xff0c;楼宇消防安全问题也日益突出。为了提高楼宇员工和居民的消防安全意识&#xff0c;楼宇VR消防安全教育培训应运而生。VR安全培训公司深圳华锐视点制作的楼宇vr消防安全教育培训&#xff0c;包括消…

初出茅庐的小李博客之STM32CubeMx配置定时器的编码器模式

STM32CubeMx配置定时器的编码器模式 上次文章写了编码器是如何工作的&#xff0c;今天就来用STM32F103C8T6的TIM3的通道1跟通道2编写一个编码器识别程序。 编程思路&#xff1a; A相:TIM3_CH1 B相:TIM3_CH2 SWITCH:PB5&#xff08;外部中断的方式&#xff09; 实现效果&a…

threejs实现水面的效果

实现水波纹的效果&#xff1a;加入几何形状&#xff0c;可以将平台的几何形状 const waterGeometry new THREE.PlaneGeometry( 10000, 10000 ); 引入水的插件&#xff0c;并修改水的材质。 import { Water } from three/addons/objects/Water.js;const water new Water(water…

【Java】常见面试题:网络

目录 1. 为什么需要网络协议的分层&#xff1f;2. 【封装和分用】3. Socket套接字主要针对传输层协议划分为如下三类&#xff08;了解&#xff09;4. 简单说一下TCP和UDP的区别&#xff1a;5. TCP中的长短连接6. 应用层重点协议7. TCP可靠传输机制&#xff08;三次握手四次挥手…

excel中定位条件,excel中有哪些数据类型、excel常见错误值、查找与替换

一、如何定位条件 操作步骤&#xff1a;开始 - 查找和选择 - 定位条件&#xff08;ctrl G 或 F5&#xff09; 注&#xff1a;如果F5不可用&#xff0c;可能是这个快捷键被占用了 案例&#xff1a;使用定位条件选择取余中空单元格&#xff0c;填入100&#xff0c;按组合键ct…

C++之signal信号应用实例(一百七十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

Docker容器:docker基础及安装

文章目录 一.docker容器概述1.什么是容器2. docker与虚拟机的区别2.1 docker虚拟化产品有哪些及其对比2.2 Docker与虚拟机的区别 3.Docker容器的使用场景4.Docker容器的优点5.Docker 的底层运行原理6.namespace的六项隔离7.Docker核心概念 二.Docker安装 及管理1.安装 Docker1.…