C#委托实现C++ Dll中的回调函数

2 篇文章 0 订阅

 很多的Dll都是CC++写的,那么如果C#想要调用Dll中的函数怎么办,尤其是Dll函数其中一个参数是函数指针的,即里面有回掉函数的用C#怎么实现?

C中的回掉函数在C#中有中特殊的处理方式叫委托,即要实现的回掉函数委托给另一个和它返回值类型以及函数参数类型、数量一样的方法来实现。


一、新建项目Visual C++  Win32控制台应用,工程名为CcreateDll,解决方案名为Dlltest

 

确定—>下一步

 

 

应用程序类型选Dll>完成

 

新建头文件Ccreate.h,声明导出函数,其中API_DECLSPEC int CallPFun(addP callback, inta, int b) 第一个参数为函数指针,内容如下:

 

#pragma once

#ifndef Ccreate_H_
#define Ccreatel_H_

typedef  int(*addP)(int, int);

#ifdef _EXPORTING 
#define API_DECLSPEC extern "C" _declspec(dllexport) 
#else 
#define API_DECLSPEC  extern "C" _declspec(dllimport) 
#endif

API_DECLSPEC int Add(int plus1, int plus2);
API_DECLSPEC int mulp(int plus1, int plus2);
API_DECLSPEC int CallPFun(addP callback, int a, int b);

#endif

头文件有了,在CcreateDll.cppinclude头文件,并实现相关函数。Ccreate.cpp如下

 

// CcreateDll.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include <iostream> 
#include "Ccreate.h"

using namespace std;

int Add(int plus1, int plus2)
{
	int add_result = plus1 + plus2;
	return add_result;
}
int mulp(int plus1, int plus2)
{
	int add_result = plus1 * plus2;
	return add_result;
}

int CallPFun(int(*callback)(int, int), int a, int b) {
	return callback(a, b);
}

函数CallPFun实际就是传入函数指针及其参数,内部直接调用函数指针。

Release模式下生成CcreateDll工程

 

生成成功后在解决方案目录的Release文件夹下会看到生成的CcreateDll.dll,使用Dll查看工具可以看到三个导出函数。

 

二、新建C#控制台工程CsharpCallDll实现调用Dll并使用委托实现回掉。

 

 

CsharpCallDll工程Program.cs如下:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace CsharpCallDll
{
    public class Program
    {
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate int DllcallBack(int num1, int num2);

        [DllImport(@"../../../Release/CcreateDll.dll", EntryPoint = "Add", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        extern static int Add(int a, int b);

        [DllImport(@"../../../Release/CcreateDll.dll", EntryPoint = "mulp", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        extern static int mulp(int a, int b);

        [DllImport(@"../../../Release/CcreateDll.dll", EntryPoint = "CallPFun", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public extern static int CallPFun(DllcallBack pfun, int a, int b);
        //[MarshalAs(UnmanagedType.FunctionPtr)]
        static void Main(string[] args)
        {
            int a = 3;
            int b = 4;
            int result;
            DllcallBack mycall;
            mycall = new DllcallBack(Program.CsharpCall);
            result = Add(a, b);
            Console.WriteLine("Add 返回{0}", result);
            result = mulp(a, b);
            Console.WriteLine("mulp 返回{0}", result);
            result = CallPFun(mycall, a, b);
            Console.WriteLine("dll回掉 返回{0}", result);
            Console.ReadLine();
        }

        public static int CsharpCall(int a, int b)
        {
            return a * a + b * b;
        }
    }
}

    

通过DllImport导入相应的Dll并声明Dll中的导出函数,CcreateDll.dll中导出函数CallPFun有三个参数,原型为

 

int CallPFun(int(*callback)(int, int), int a, int b) {
	return callback(a, b);
   }
   

参数1为一个带两个int参数的返回值为int型的函数指针,这里声明一个委托

public delegate int DllcallBack(int num1, intnum2);

该委托可以指向任何带两个int型参数且返回值为int型的方法,这里的CsharpCall方法可以看作是回掉函数的实现。

 

public static int CsharpCall(int a, int b)
   {
            return a * a + b * b;
   }
   

通过        DllcallBack mycall;

           mycall = new DllcallBack(Program.CsharpCall);

  把实际要完成的工作交给CsharpCall去完成。

    运行CsharpCallDll,结果如下:

 

 

是不是实现了C#委托实现回掉

 

最后还有如果声明委托时在public delegate int DllcallBack(int num1, int num2);上面没有[UnmanagedFunctionPointer(CallingConvention.Cdecl)]这一句,那么运行时将会出现System.AccessViolationException异常,如下

 

 

还有Dll调用约定,CallingConvention.有五种调用方式

CallingConvention= CallingConvention.StdCall

CallingConvention= CallingConvention.Cdecl

CallingConvention= CallingConvention.FastCall

CallingConvention= CallingConvention.ThisCall

CallingConvention= CallingConvention.Winapi

到底使用哪种方式,网上有说"Bydefault, C and C++ use cdecl - but marshalling uses stdcall to match theWindows API."即默认情况下,CC++使用的Cdecl调用,但编组使用StdCall调用匹配的Windows API,对于FastCallThisCallWinapi这三种调用方式尚不清楚。

这里将CallingConvention= CallingConvention.Cdecl改成CallingConvention = CallingConvention.StdCall,重新运行导致堆栈不对称如下

 



 




  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本手册各章节内容如下: z 总述。主要介绍 S5500-EI系列以太网交换机的资料获取方式、产品简介和组网 应用。 z 登录以太网交换机。 主要介绍登录 S5500-EI系列以太网交换机可以采用的几种 方法。 z VLAN。主要介绍 VLAN、Voice VLAN、GVRP的原理和相关配置。 z IP地址-IP性能。主要介绍 IP地址及IP性能的原理和相关配置。 z QinQ-BPDU TUNNEL。主要介绍 QinQ和 BPDU TUNNEL的特性原理和相关 配置。 z 端口相关配置。主要介绍以太网端口的基本配置和端口隔离配置。 z 链路聚合。主要介绍链路聚合的原理和相关配置。 z MAC地址转发表管理。主要介绍 MAC地址转发表的学习、老化机制和相关配 置。 z IP Source Guard。主要介绍对 MAC地址、IP地址和端口进行绑定的原理和 相关配置。 z DLDP。主要介绍 DLDP的原理和相关配置。 z MSTP。主要介绍生成树协议的原理和相关配置。 z 路由-GR概述。主要介绍路由基础知识、路由协议的分类和 GR的基本原理。 z IPv4路由。主要介绍静态路由、RIP、OSPF、IS-IS、BGP、路由策略等 IPv4 路由相关配置。 z IPv6 路由。主要介绍 IPv6 静态路由、RIPng、OSPFv3、IS-ISv6、BGP4+等 IPv6路由相关配置。 z IPv6配置。主要介绍 IPv6基础配置及应用,IPv6隧道、双协议栈等相关配置。 z 组播协议。主要介绍 IGMP Snooping、MLD Snooping、组播 VLAN、组播策 略、IGMP、PIM-DM、PIM-SM、MSDP等组播相关配置。 z 802.1x-HABP-MAC地址认证。主要介绍 802.1x、HABP、MAC地址认证的相 关配置。 z AAA-RADIUS-HWTACACS。主要介绍 AAA、RADIUS、HWTACACS的相关 配置。 z ARP。主要介绍 ARP基本原理、ARP源抑制、ARP代理功能的相关配置。 z DHCP 。 主要介绍 DHCP Server 、 DHCP Relay 、 DHCP Client 和 DHCP-Snooping的原理和相关配置。 z ACL。主要介绍多种基于 IPv4及 IPv6的 ACL配置方法。 z QoS。主要介绍 QoS的原理及相关配置。 z 端口镜像。主要介绍端口镜像的相关配置。 z 集群管理。主要介绍集群管理的原理和相关配置。 z UDP Helper。主要介绍UDP HELPER的相关配置。 z SNMP-RMON。 主要介绍利用SNMP&RMON对网络设备进行管理的相关配置。 z NTP。主要介绍 NTP的原理和相关配置。 z 域名解析。主要介绍域名解析特性的原理和相关配置。 z 文件系统管理。主要介绍文件系统管理、配置文件管理,及使用 FTP和 TFTP 进行文件操作的相关配置。 z 信息心。主要介绍利用信息心进行网络运行情况分析和诊断的相关配置。 z 系统维护与调试。主要介绍如何对系统进行日常的维护和调试。 z NQA。主要介绍 NQA的原理和相关配置。 z VRRP。主要介绍 VRRP的原理和相关配置。 z SSH。主要介绍 SSH的原理和相关配置。 z RRPP。主要介绍 RRPP的原理和相关配置。 z 端口安全。主要介绍端口安全的原理和相关配置。 z LLDP。主要介绍 LLDP的原理和相关配置。 z PoE。主要介绍 PoE的原理和相关配置。 z sFlow。主要介绍 sFlow的原理和相关配置。 z SSL-HTTPS。主要介绍SSL及 HTTPS的原理和相关配置。 z PKI。主要介绍 PKI的原理和相关配置。 z Track。主要介绍 Track的原理和相关配置。 z 附录。主要介绍本书的缩略语。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值