How to make a callback to C# from C/C++ code
2015-05-12 12:38
260 查看
How to make a callback to C# from C/C++ code
Tecfield, 26
Jun 2013 CPOL
60.1K
66
4.94 (33 votes) |
|
Is your email address OK? You are signed up for our newsletters
but your email address is either unconfirmed, or has not been reconfirmed in a long time. Please click here to
have a confirmation email sent so we can confirm your email address and start sending you newsletters again. Alternatively, you can update
your subscriptions.
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:
Hide Copy 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 –
Hide Copy Code
[UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate void ProgressCallback(int value);
Define callback signature in the C code –
Hide Copy Code
typedef void (__stdcall * ProgressCallback)(int);
Change
DoWorksignature in C code to accept
ProgressCallbackaddress:
Hide Copy Code
DLL void DoWork(ProgressCallback progressCallback)
Note: DLL is…
Hide Copy Code
#define DLL __declspec(dllexport)
Inside the C# code, we need to create a delegate of type of the unmanaged delegate –
Hide Copy Code
ProgressCallback callback = (value) => { Console.WriteLine("Progress = {0}", value); };
Then for calling
DoWork, we need to do it like this –
Hide Copy Code
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
Hide Copy Code
#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
Hide Shrink
Copy Code
#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
Hide Shrink
Copy Code
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
相关文章推荐
- 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 read data from csv file in c#
- How to play XM Music From your own code
- How to migrate from code-centric to model-centric development using Rational Software Architect
- How to create WSDL SourceCode from a webservice.
- <From C++ To C#> 更强大的值类型
- [导入]How can I run another application or batch file from my Visual C# .NET code?
- How to change the generated method stub code for C#
- How to generate UML Diagrams from Java code in Eclipse
- How to programmatically generate C# files from a DLL or EXE
- How to use gcov to get code coverage from static library in iphone?
- How to generate xml through c# code for below xml sample
- How to Use C++ With PHP and JQuery to Make Neat Apps
- Calling C++ code from C# z
- C++ Portability Guide (How to write portable code)
- How to use the PECL HTTP (PECL_HTTP) Extension to make HTTP requests from PHP
- io - make c++ vector read/write from/to a file - Stack Overflow