How to make a callback to C# from C/C++ code
2013-06-30 08:18
555 查看
注:个人觉得这篇技术文章很有价值,收藏下,本来想翻译一下,最近有点懒,过两天再说。
http://www.codeproject.com/Tips/318140/How-to-make-a-callback-to-Csharp-from-C-Cplusplus
Almost
everyone knows how to make a call to a function in an unmanaged DLL. However, sometimes we wish that we could call C# code from C/C++ code.
Imagine a scenario wherein we have a C# application which has a native C DLL called Engine.dll.
There is a function entry named “
DoWork” in this
DLL that we need to call. Calling
DoWorkin the
engine is as easy as making the following declaration in the C# code:
[DllImport("Engine.dll")] public static extern void DoWork();
…and then using it like any other
staticC#
method in our C# application.
This will work just fine. However, let’s assume
DoWorkis
a long-running task and we want to show a progress or so in the C# app in order to keep our user(s) updated. To make this happen, we need to…
Define an unmanaged delegate in the C# code like –
[UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate void ProgressCallback(int value);
Define callback signature in the C code –
typedef void (__stdcall * ProgressCallback)(int);
Change
DoWorksignature in C code to accept
ProgressCallbackaddress:
DLL void DoWork(ProgressCallback progressCallback)
Note: DLL is…
#define DLL __declspec(dllexport)
Inside the C# code, we need to create a delegate of type of the unmanaged delegate –
ProgressCallback callback = (value) => { Console.WriteLine("Progress = {0}", value); };
Then for calling
DoWork, we need to do it like this –
DoWork(callback);
Here is a sample source code for a simple application. This code snippet includes a second scenario wherein we have a function in C code called
ProcessFilethat
needs to get back to the C# in order to obtain a file path for further processing - in this case, printing its contents to the console.
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);
}
}
Enjoy it
License
This article, along with any associated source code and files, is licensed under TheCode Project Open License (CPOL)
相关文章推荐
- How to make a callback to C# from C/C++ code
- Node.js howto: make asynchronous callback from thread
- Talk about how to write good C# code from a bug
- How to call C/C++ sytle function from C# solution?
- How to pass macro definition from “makefile” command line arguments to C source code?
- How to hide & unhide the grid from the page by using people code?
- c++ how to make your own class a valid key type for std::map?
- How to Use C++ With PHP and JQuery to Make Neat Apps
- Calling C++ code from C# z
- <From C++ To C#> 那就开始吧
- How to make a sprite from URL in cocos2d-x
- How to use an Outlook Object Model from Visual C++ by using a #import statement
- How to unlock xcode file to make edits from different computers?
- Socket programing(make a chat software) summary 1:How to accsess LAN from WAN
- How to rebuild assemblies from the source code
- <From C++ To C#>进军到函数
- How to run an existing SQL Server Agent Job from C#
- c# how to make app use a specified configure file
- How to use C# code to get the windows components
- Beginning C# Objects From Concepts to Code