0
点赞
收藏
分享

微信扫一扫

样从C/C++代码中对C#进行回调

声明:网络上类似的中文博客大有存在,本人知识水平有限,业余爱好,也是为了备份收藏​​How to make a callback to C# from C/C++ code​​

本着共享知识的初衷,翻译一份给大家参考,为了便于阅读不至于拗口,没有按照原文直译,不到之处或者翻译有误,还望勿喷,敬请指评。

 

几乎每个人都知道怎样调用一个非托管DLL中的函数,然而有时候我们希望能从C/C++代码中调用C#代码。
想象一个场景,其中有一个名为Engine.dll的本机C语言编写DLL的C#应用程序。在DLL中有一个名为“DoWork
的函数入口点,我需要对它进行调用。在Engine.dll中调用"DoWork"就像在C#代码中做以下声明一样简单。

[DllImport("Engine.dll")]
public static extern void

这段代码运行将非常良好,然而,让我再假设一下DoWork是一个连续性运行的任务,为了保证我们的用户端可被更新,
我们希望显示一个进度。想要实现这一点,我们需要做出以下几步:

 1.在C#代码中定义一个类似的非托管代码委托

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void ProgressCallback(int

2.在C代码中定义一个回调签名

typedef void (__stdcall * ProgressCallback)(int);

3.在C代码中更改DoWork的签名以便接收ProgressCallback的地址

DLL void

注意:DLL宏的声明是这样的

#define

4.在C#代码中,我们需要创建一个非托管委托类型的委托

ProgressCallback callback =
(value) =>
{
Console.WriteLine("Progress = {0}", value);
};

5.然后为了调用DoWork,我们需要这样做

DoWork(callback);

这里有一个简单应用程序的示例源码.这个代码段包含其他代码套方案,其中有一个名为ProcessFile函数的C代码需要回调到C#,以便获得文件
路径进行用于进一步处理 - 当前情形下将打印文件的内容到控制台。

Engine.dll/Main.h

#include "Windows.h"

#ifdef __cplusplus
extern "C"
{
#endif

#define DLL __declspec(dllexport)
typedef void (__stdcall * ProgressCallback)(int);
typedef char* (__stdcall * GetFilePathCallback)(char* filter);

DLL void DoWork(ProgressCallback progressCallback);
DLL void ProcessFile(GetFilePathCallback getPath);

#ifdef __cplusplus
}
#endif

Engine.dll/Main.c

 

#include "Main.h"
#include <stdio.h>

DLL void DoWork(ProgressCallback progressCallback)
{
int counter = 0;

for(; counter<=100; counter++)
{
// do the work...

if (progressCallback)
{
// send progress update
progressCallback(counter);
}
}
}

DLL void ProcessFile(GetFilePathCallback getPath)
{

if (getPath)
{
// get file path...
char* path = getPath("Text Files|*.txt");
// open the file for reading
FILE *file = fopen(path, "r");
// read buffer
char line[1024];

// print file info to the screen
printf("File path: %s\n", path ? path : "N/A");
printf("File content:\n");

while(fgets(line, 1024, file) != NULL)
{
printf("%s", line);
}

// close the file
fclose(file);
}
}

 

TestApp.exe/Program.cs

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

class Program
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
delegate void ProgressCallback(int value);

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
delegate string GetFilePathCallback(string filter);

[DllImport("Engine.dll")]
public static extern void DoWork([MarshalAs(UnmanagedType.FunctionPtr)] ProgressCallback callbackPointer);

[DllImport("Engine.dll")]
public static extern void ProcessFile([MarshalAs(UnmanagedType.FunctionPtr)] GetFilePathCallback callbackPointer);

[STAThread]
static void Main(string[] args)
{
// define a progress callback delegate
ProgressCallback callback =
(value) =>
{
Console.WriteLine("Progress = {0}", value);
};

Console.WriteLine("Press any key to run DoWork....");
Console.ReadKey(true);
// call DoWork in C code
DoWork(callback);

Console.WriteLine();
Console.WriteLine("Press any key to run ProcessFile....");
Console.ReadKey(true);

// define a get file path callback delegate
GetFilePathCallback getPath =
(filter) =>
{
string path = default(string);

OpenFileDialog ofd =
new OpenFileDialog()
{
Filter = filter
};

if (ofd.ShowDialog() == DialogResult.OK)
{
path = ofd.FileName;
}

return path;
};

// call ProcessFile in C code
ProcessFile(getPath);
}
}

以下附上本人编译的代码,和原文有点出入,主要是因为本人习惯用.NET 2.0,还有一些是为了编译期间顺利通过编译器。

代码使用Visual Studio 2010+VC6.0编写

下载地址:1.怎样从C_C++代码中对C#进行回调.rar

            2.怎样从C_Cpp代码中对CSharp进行回调2.rar


举报

相关推荐

0 条评论