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

原创 2017年03月18日 17:26:29

 很多的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,重新运行导致堆栈不对称如下

 



 




版权声明:本文为博主原创文章,未经博主允许不得转载。

c#调用c++带有回调函数方法的实现

在c++中有个回调函数指针的概念,只需要某个函数在调用定时器函数时传入一个函数指针就能达到目的,但C#中没有函数指针的概念,我们该怎样来实现呢。 其实说到回调函数,大家应该能想到c#中的委托,虽然名...
  • songjinshi
  • songjinshi
  • 2012年11月06日 16:41
  • 12584

C# 调用dll 回调函数

C/C++内回调函数一般通过传递函数指针来实现,函数指针在C#中对应的就是委托.   Cpp代码   // 传入函数指针  typedef void (*FUNC)(int,...
  • snakorse
  • snakorse
  • 2014年03月08日 01:51
  • 1882

C#调用C++DLL,及回调函数、string参数传递的总结

Int型传入: Dll端: extern "C" __declspec(dllexport) int Add(int a, int b) {     return ...
  • xuedingkai
  • xuedingkai
  • 2016年11月29日 18:30
  • 710

DLL函数调用以及回调函数设置

在window开发中,紧张要将一些库编译成DLL以共享给其他程序使用,那么怎样调用DLL函数 1.只是普通调用DLL中的函数 1.1在VS2012中创建一个DLL程序,如MyDLL。 新建一个Myco...
  • ranky2009
  • ranky2009
  • 2015年01月27日 17:55
  • 3727

C#与C++回调交互

先总结一部分 using System.Collections; using System.Collections.Generic; using System.Runtime.InteropSer...
  • AGroupOfRuffian
  • AGroupOfRuffian
  • 2017年11月14日 14:18
  • 177

C#调C++动态库Dll C++回调C#函数

vs2010 新建项目 / Visual C++ / 类库; 项目名  MyCallbackDll 头文件: 定义类 成员函数 // MyCallbackDll.h #pragma once us...
  • youqingyike
  • youqingyike
  • 2015年10月14日 14:24
  • 1153

.NET 回调函数

[文章来源:.NET SDK文档]回调函数是托管应用程序中可帮助非托管 DLL 函数完成任务的代码。对回调函数的调用将从托管应用程序中,通过一个 DLL 函数,间接地传递给托管实现。在用平台调用调用的...
  • jiangxinyu
  • jiangxinyu
  • 2008年04月21日 09:41
  • 1510

C# 调用C/C++回调函数

http://tcspecial.iteye.com/blog/1675621 C/C++内回调函数一般通过传递函数指针来实现,函数指针在C#中对应的就是委托.   Cpp代...
  • cocoasprite
  • cocoasprite
  • 2015年08月22日 00:17
  • 1256

Unity3d 调用 C++ DLL之 DLL回调Unity3d (C++ DLL回调 C#函数)

上篇 Unity3d 调用C++ DLL (Win平台) 介绍了简单的 Unity3d 调用 C++ DLL的方法,但是这样是不够的,这里再讲下通过函数指针让 C++ DLL中回调 Unity3...
  • cp790621656
  • cp790621656
  • 2015年05月15日 20:16
  • 5091

C++通过Callback向C#传递数据

C++通过Callback向C#传递数据 本文转载于:http://www.roboby.com/c%E9%80%9A%E8%BF%87callback%E5%90%91c%E4%BC%A0%E9%8...
  • hzqnju
  • hzqnju
  • 2015年03月18日 11:22
  • 4807
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#委托实现C++ Dll中的回调函数
举报原因:
原因补充:

(最多只允许输入30个字)