C# 集成 C++ 的方法和实践 - P/Invoke(平台调用)- 1

环境:


P/Invoke(平台调用):

C#可以通过P/Invoke调用C++编写的DLL中的函数。

1.1 适用范围:

P/Invoke 是一种在 C# 程序中调用非托管代码(如 C++ 动态链接库)的方式。这种方法适用于函数调用相对简单的情况。

1.2 步骤:

  • 在 C++ 中编写算法并编译生成 DLL。
  • 在 C# 项目中使用 DllImport 属性引入 DLL。

 1.3 案例程序:

1.3.1 新建一个ExportedFunctions.cpp【函数调用法】

// MathFunctions.cpp
#include "MathFunctions.h"

int Add(int a, int b) {
    return a + b;
}

特点

  • 使用了extern "C",这告诉编译器按照C语言的方式处理函数名,避免了名称修饰。
  • 使用了__declspec(dllexport),这指示编译器导出该函数,使其在DLL中可见。
  • 这是一个自由函数(不属于任何类),可以直接被P/Invoke调用。

1.3.2 新建一个 ExportedFunctions.h

// MathFunctions.h
#pragma once

extern "C" {
    __declspec(dllexport) int Add(int a, int b);
}

 1.3.3 在C#中调用动态库的函数:

using System;
using System.Runtime.InteropServices;

class Program
{
    // 使用DllImport属性声明DLL中的函数
    [DllImport("MathFunctions.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int Add(int a, int b);

    static void Main(string[] args)
    {
        // 调用DLL中的Add函数
        int result = Add(5, 10);
        Console.WriteLine("The result of adding 5 and 10 is: " + result);
    }
}

2 VS STUDIO 生成DLL的DllMain模板给出的意义:

2.1 dllmain.cpp文件

包含了DllMain函数的框架。DllMain是DLL的入口点,它是一个特殊的函数,由Windows操作系统在DLL的生命周期中的关键时刻自动调用。这个函数的原型由Windows API定义,其作用是处理DLL的各种加载和卸载事件。

// 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;
}

DllMain函数的参数如下:

  • HMODULE hModule:被加载DLL的模块句柄。
  • DWORD ul_reason_for_call:调用原因代码,指示为什么调用DllMain
  • LPVOID lpReserved:保留参数,用于特定调用原因的附加信息。

ul_reason_for_call参数可以有以下几种值:

  • DLL_PROCESS_ATTACH:DLL被加载到地址空间中时调用。这是初始化DLL设置的好地方,例如全局变量的初始化。
  • DLL_THREAD_ATTACH:一个新线程被创建到包含DLL的进程中时调用。这允许DLL为每个线程设置特定的数据。
  • DLL_THREAD_DETACH:一个线程结束时调用,不再需要DLL的服务。这可以用来清理线程特定的数据。
  • DLL_PROCESS_DETACH:DLL从进程的地址空间卸载时调用。这是执行清理工作,如释放资源和注销全局变量的好地方。

DllMain函数中,每个case对应一个调用原因。在默认情况下,Visual Studio生成的模板代码中,这些case下没有任何操作,只是简单的break语句。这意味着DLL在加载和卸载时不会执行任何特别的操作。如果你需要在DLL加载或卸载时执行特定的初始化或清理代码,你可以在相应的case下添加你的代码。例如:

switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
    // 初始化代码,如分配资源
    break;
case DLL_THREAD_ATTACH:
    // 线程特定初始化代码
    break;
case DLL_THREAD_DETACH:
    // 线程退出时的清理代码
    break;
case DLL_PROCESS_DETACH:
    // 进程退出时的清理代码,如释放资源
    break;
}

3 在VS 2019中,融合DllMain模板和P/Invoke(平台调用)

 3.1 在C#中进行集成:

将编译好的DLL文件放在你的C#项目可以访问到的位置。

我现在项目目录下,构建了一个lib目录,

然后,在C#中引入dll,

添加,编译好的C++库


问题:

1 尝试引入DLL

解决:

当您使用P/Invoke调用非托管代码(如C++ DLL)时,不需要注册DLL或将其作为COM组件。 

确保dll文件位于C#项目的输出目录中(如bin/Debugbin/Release),或者将DLL文件路径添加到系统PATH环境变量中。

 2 无法找到入口:

Error: 无法在 DLL“AAMED_DLL_DEMO1.dll”中找到名为“Add”的入口点。
 

 笔者的地址在下面:

D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.20.27508\bin\HostX64\x64 

 执行命令如下:

 .\dumpbin.exe /EXPORTS K:\Prj_MotosCatch\Prj_Src\AAMED_LIB_Demo\AAMED_DLL_DEMO1\x64\Debug\AAMED_DLL_DEMO1.dll

结果:

PS D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.20.27508\bin\HostX64\x64> .\dumpbin.exe /EXPORTS K:\Prj_MotosCatch\Prj_Src\AAMED_LIB_Demo\AAMED_DLL_DEMO1\x64\Debug\AAMED_DLL_DEMO1.dll
Microsoft (R) COFF/PE Dumper Version 14.20.27525.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file K:\Prj_MotosCatch\Prj_Src\AAMED_LIB_Demo\AAMED_DLL_DEMO1\x64\Debug\AAMED_DLL_DEMO1.dll

File Type: DLL

  Summary

        1000 .00cfg
        1000 .data
        2000 .idata
        1000 .msvcjmc
        3000 .pdata
        3000 .rdata
        1000 .reloc
        1000 .rsrc
        9000 .text
       10000 .textbss

 确实没有看到add的函数入口

修正代码,之前想按CLASS来写不行:

然后,重新执行:

PS D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.20.27508\bin\HostX64\x64> .\dumpbin.exe /EXPORTS K:\Prj_MotosCatch\Prj_Src\AAMED_LIB_Demo\AAMED_DLL_DEMO1\x64\Debug\AAMED_DLL_DEMO1.dll
Microsoft (R) COFF/PE Dumper Version 14.20.27525.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file K:\Prj_MotosCatch\Prj_Src\AAMED_LIB_Demo\AAMED_DLL_DEMO1\x64\Debug\AAMED_DLL_DEMO1.dll

File Type: DLL

  Section contains the following exports for AAMED_DLL_DEMO1.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 0001133E Add = @ILT+825(Add)

  Summary

        1000 .00cfg
        1000 .data
        2000 .idata
        1000 .msvcjmc
        3000 .pdata
        3000 .rdata
        1000 .reloc
        1000 .rsrc
        9000 .text
       10000 .textbss

这时候,已经能看到Add的函数定义了,运行后结果正常,可以运行DLL的函数内容。


本文的案例代码:需要知识付费:

https://download.csdn.net/download/yellow_hill/89396682

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[职场] 美术指导的重要作用 #学习方法#笔记

美术指导的重要作用 美术指导是广告、电影、电视剧等创意作品中的一个重要角色,负责整体视觉风格和美术设计的指导和管理。 美术指导的目标是通过视觉表达来传达故事的情感、氛围和主题,以及塑造角色和场景的形象。 美术指导在创作过程中扮演着重要的角…

基于Java Mq的数据交换平台实现_设计消息的格式和内容

基于Java Mq的数据交换平台实现 目录概述需求: 设计思路实现思路分析 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,challen…

前端UI框架Element Plus 和 Ant Design Vue哪个好

Element Plus 和 Ant Design Vue 都是基于 Vue.js 的 UI 组件库,它们具备一系列可复用的组件和丰富的功能,并且是当前国内主流的两个 UI 组件库。 (1)Element Plus 是饿了么前端团队推出的开源项目,是对 Element UI 的…

一文搞懂Python的异常

人生之事,不如意者十之有九。 在编程中亦是如此。异常(Exception),遍布于程序各个角落,开发工作的大部分coding,都是为了应对和解决它。 概念 异常,简而言之,是程序在执行期间发生的非预期的、非正常的事件或情况。 举个实际生活的例子: 你周末出门买大龙虾,但当你…

Docker 管理 | 代理配置、内网共享和 Harbor 部署

唠唠闲话 在现代软件开发和运维中,容器技术已经成为构建、部署和管理应用程序的标准工具。然而,在实际操作中,我们常常需要面对一些常见的挑战,如容器访问外部资源的代理配置、内网环境下的镜像共享以及企业级镜像管理。 本教程…

[linux] makefilegdb理解

目录 Linux项目自动化构建工具-make/Makefile 背景 理解 依赖关系 依赖方法 原理 Linux调试器-gdb使用 背景 开始使用 Linux项目自动化构建工具-make/Makefile 背景 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力 一个工…

问题:脾梗塞时,下列情况最符合的是 #职场发展#知识分享#媒体

问题:脾梗塞时,下列情况最符合的是 A、脾肿大 B、脾区摩擦感 C、两者均有 D、两者均无 参考答案如图所示

[线程与网络] 网络编程与通信原理(六):深入理解应用层http与https协议(网络编程与通信原理完结)

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏:🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 🧀Java …

Java Web学习笔记20——Ajax-Axios

Axios: 介绍:Axios对原生的Ajax进行封装,简化书写,快速开发。 官网:https://www.axios-http.cn Axios 入门: {}是Js的对象。 get的请求参数是在URL后面?和相关参数值。 post的请求参数是在请…

【设计模式】JAVA Design Patterns——State(状态模式)

🔍目的 允许对象在内部状态改变时改变它的行为。对象看起来好像修改了它的类。 🔍解释 真实世界例子 当在长毛象的自然栖息地观察长毛象时,似乎它会根据情况来改变自己的行为。它开始可能很平静但是随着时间推移当它检测到威胁时它会对周围的…

树莓派 5 AI 套件(Hailo)示例

系列文章目录 前言 欢迎访问 Hailo Raspberry Pi 5 示例库。本项目展示了在 Raspberry Pi 5 上演示 Hailo AI 处理器功能的各种示例。这些示例将帮助您开始在嵌入式设备上使用人工智能。更多信息,请访问 Hailo 官方网站和 Hailo 社区论坛。 一、如何设置 Raspberry…

问题:功夫菜产品的成本由哪几方面构成() #经验分享#其他

问题:功夫菜产品的成本由哪几方面构成() A.材料成本(标准投料2%损耗)包材成本直接人工费固定加工费 B.(材料成本包材成本)*(1加价率) C&#x…

【kubernetes】探索k8s集群的配置资源(secret和configma)

目录 一、Secret 1.1Secret 有四种类型 1.2Pod 有 3 种方式来使用 secret 1.3应用场景:凭据 1.4创建 Secret 1.4.1用kubectl create secret命令创建Secret 1.4.2内容用 base64 编码,创建Secret 1.4.2.1Base64编码 1.4.2.2创建YAML文件 1.4.2.3…

2021年vue面试题整理(万字解析)

一、对MVVM的理解 MVVM分为Model、View、ViewModel。 Model 代表数据模型,数据和业务逻辑都在Model层中定义;泛指后端进行的各种业务逻辑处理和数据操控,对于前端来说就是后端提供的 api 接口。 View 代表UI视图,负责数据的展示…

Windows系统中好用的闪迪U盘修复工具

本文向你介绍了一款简单好用的闪迪U盘修复工具,它可以帮助你轻松修复闪迪U盘的各种问题。该工具操作简单,能帮用户节省大量的时间和精力。 闪迪U盘损坏可以修复吗? “我有一只32GB的闪迪U盘出现了问题,可能是因为我在关机前将它强…

基于51单片机水塔水位控制系统

基于51单片机水塔水位控制 (仿真+程序) 功能介绍 具体功能: 1.用滑动变阻器模拟水位,ADC0809将模拟信号转换为数字信号; 2.LCD1602显示当前水位和水位阈值; 3.当水位超过设定阈值&#xff…

Linux系统之部署Blog-Index导航页

Linux系统之部署Blog-Index导航页 一、Blog-Index介绍1.1 Blog-Index简介1.2 Blog-Index特点1.3 Blog-Index使用场景 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍2.3 Yarn介绍 三、检查本地环境3.1 检查本地操作系统版本3.2 检查系统内核版本3.3 检查系统是否安装yarn 四…

C语言scanf( ) 函数、fprintf( ) 函数与 scanf( ) 函数和printf( ) 函数有什么不同?

一、问题 fscanf( ) 函数、fprintf( ) 函数与 printf( ) 函数、scanf( ) 函数的作⽤相似,都是格式化读写函 数,那么这两个读写函数有什么不同呢? 二、解答 两者的区别就在于前⾯的字符“f”,即 fscanfQ函数和 fprintfD函数的读写…

2005-2022年各省居民人均消费支出数据(无缺失)

2005-2022年各省居民人均消费支出数据(无缺失) 1、时间:2005-2022年 2、来源:国家统计局、统计年鉴 3、指标:全体居民人均消费支出 4、范围:31省 5、缺失情况:无缺失 6、指标解释 居民人…

【经验分享】搭建跨境电商那个独立站必备的功能模块以及实现

搭建跨境电商独立站时,需要确保网站具备一系列关键的功能板块,以提供用户友好的购物体验并确保业务的顺利进行。以下是这些功能板块的详细归纳: 注册登录与身份验证: 用户注册与登录:允许用户创建账户,通过…