注:个人觉得这篇技术文章很有价值,收藏下,本来想翻译一下,最近有点懒,过两天再说。
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 calledEngine.dll.
There is a function entry named “DoWork
” in this
DLL that we need to call. CallingDoWork
in 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 otherstatic
C#
method in our C# application.
This will work just fine. However, let’s assumeDoWork
is
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
DoWork
signature in C code to acceptProgressCallback
address:
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 calledProcessFile
that
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++)
{
if (progressCallback)
{
progressCallback(counter);
}
}
}
DLL void ProcessFile(GetFilePathCallback getPath)
{
if (getPath)
{
char* path = getPath("Text Files|*.txt");
FILE *file = fopen(path, "r");
char line[1024];
printf("File path: %s\n", path ? path : "N/A");
printf("File content:\n");
while(fgets(line, 1024, file) != NULL)
{
printf("%s", line);
}
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)
{
ProgressCallback callback =
(value) =>
{
Console.WriteLine("Progress = {0}", value);
};
Console.WriteLine("Press any key to run DoWork....");
Console.ReadKey(true);
DoWork(callback);
Console.WriteLine();
Console.WriteLine("Press any key to run ProcessFile....");
Console.ReadKey(true);
GetFilePathCallback getPath =
(filter) =>
{
string path = default(string);
OpenFileDialog ofd =
new OpenFileDialog()
{
Filter = filter
};
if (ofd.ShowDialog() == DialogResult.OK)
{
path = ofd.FileName;
}
return path;
};
ProcessFile(getPath);
}
}
Enjoy it
分享到:
相关推荐
现在比较流行C#与C++融合:C#做GUI,开发效率高,C++做运算,运行效率高,二者兼得。 但是C++与C#必然存在数据交互,C#与C++dll的数据交互从来都是一个让人头疼的问题。 从调用方式看也有两种情况: 1、C#调用C++...
这段时间调用C++的DLL带有CALLBACK回调参数的方法,经过一端时间研究,已经成功调用了,拿出去同大家分享一下
本文实例分析了C++中回调函数(CallBack)的用法。分享给大家供大家参考。具体分析如下: 如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过。 其错误是普通的C++成员函数都隐含了一个传递...
How to update a modal dialog contents using a callback function(17KB)
c#调用C++ 编写的DLL文件的简单例子, DLL回调CallBack处理C#中的函数 包含一个C++ DLL 项目、一个C++调用DLL项目和一个C#调用项目
SQLite – C/C++ 安装 在 C/C++ 程序中使用 SQLite 之前,我们需要确保机器上已经有 SQLite 库。可以查看 SQLite 安装章节了解安装过程。 C/C++ 接口 API 以下是重要的 C&C++ / SQLite 接口程序,可以满足您在 C/C++...
Modbus协议封装及其在各种嵌入式芯片的移植
采用CLR技术对c++封装,相当于可以使c#直接使用c++的类
NULL 博文链接:https://regular.iteye.com/blog/1686047
LUA is pure ANSI C code, this means that if you build the code with a C++ compiler it will complain with "error LNK2001: unresolved external symbol" messages. Two easy ways exist to resolve this ...
tlscallback simple test code
Cython封装Callback函数文章 示例 http://blog.csdn.net/i2cbus/article/details/18415333
C++中回调(CallBack)的使用思路C++中回调(CallBack)的使用思路C++中回调(CallBack)的使用思路
NULL 博文链接:https://jacky-dai.iteye.com/blog/2323820
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd; //窗口句柄 MSG msg; //消息 WNDCLASS...
简单易懂,快速了解WCF如何CallBack
用C++编写的一个简单Dll被C#应用程序调用的一个例子。实现了Callback功能。
(18KB)<END><br>20,dumpsome.zip DUMPSOME is a project for Visual C++ 4.x that shows how to write a CGI server extension which uses MFC and DAO. (8KB)<END><br>21,edpos.zip EDPOS is a MDI-based ...
How to implement Windows CallBack with using delphi