65.9K
CodeProject 正在变化。 阅读更多。
Home

从非托管 Windows 自定义 DLL 调用托管 .NET 函数。

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.92/5 (11投票s)

2004年4月26日

3分钟阅读

viewsIcon

123632

downloadIcon

2

它将帮助你从非托管 DLL 函数调用托管函数。

引言

这有可能吗?

是的,这绝对有可能,但你必须记住一件事。你不能从 Win32 进程调用 .NET 函数。除非你外部加载 CLR,否则这永远不可能。因此,在本文中,我们将了解如何在 .NET 进程中,从 Windows 自定义 DLL(例如,用 VC++ 编写的 DLL)调用 .NET 函数。

这有必要吗?

是的,这会有必要。从 .NET 使用 Win32 API 的开发人员,有时需要来自非托管代码的通知传递到 .NET 环境中的托管函数(例如,通知异步调用完成)。那时,他们可以使用这种方法来完成他们的任务。

给出的示例有用吗?

不,我们仅将此代码示例用于演示目的。在此示例中,我们将从托管代码调用非托管代码,并且非托管代码本身再次调用另一个托管代码(你可以使用此技术通知 .NET 环境有关来自非托管代码的异步事件)。

基本思想

通常,我们可以通过两种方法调用函数。第一种是使用函数名称,下一种是通过函数指针。在这里,我们将从另一个(非托管)环境调用函数,因此我们不能直接使用函数名称,因此我们将使用函数指针。第一步是,我们必须将函数指针提供给非托管代码,然后非托管代码将使用此函数指针来调用托管代码。

核心内容在下图中有描述

为了检查这一点,我们将在 VC++ 中创建一个自定义 DLL,并实现两个函数。一个是 SetCallBackPointer,它接收来自托管代码的函数指针并将其存储在全局变量 pFunction 中。另一个函数 InvokeCallBack 用于使用函数指针 pFunction 调用托管代码。以下是驻留在 DLL 源文件中的代码。

// MyCustomDll.cpp
//Global Variable for store the function pointer.
 
typedef VOID (*CALLBACK_FUNCTION )();
CALLBACK_FUNCTION pFunction;
 
void SetCallBackPointer(LPVOID FnAddress);
void InvokeCallBack();
 
 
//This function receive the address of the CallBack function as
//parameter and store it in a global variable to enable other function in 
// the DLL to call the CallBack Function.
 
void SetCallBackPointer(LPVOID FnAddress)
{
      pFunction = (CALLBACK_FUNCTION)FnAddress;
// For demonstration purpose only. In real World we may call 
// this function in response to a asynchronous message.
      InvokeCallBack();
}
 
// this function will Invoke the callback function 
// through the function pointer.
void InvokeCallBack()
{
     (pFunction)(); // simply calls the Callback function through pointer.
}

然后,我们必须导出 SetCallBackPointer,使其可以从 DLL 外部调用。

// MyCustomDll.def
//
LIBRARY MYCUSTOMDLL
EXPORTS
SetCallBackPointer

好的,现在我们可以构建我们的 DLL 并创建 MyCustomDll.dll。接下来,我们将编写 C# 代码来实现回调函数

//       Managed.cs 
//
 
//  Our Callback function which will be called by unmanaged code(Form windows dll).
public static void CallbackFunction()
{
      MessageBox.Show( “CallBack Function Called by Windows DLL”);
}

我们不能像在 C、C++ 或 VC++ 中那样直接将函数名称作为函数指针给出。幸运的是,我们可以使用委托来实现。(我希望大家都熟悉 .NET 的一个很棒的未来:委托。如果你不熟悉委托,请参考 MSDN。)

让我们声明一个委托并按如下方式实例化它。

// Declaring Delegate for Callback Function
// note that the Delegate prototype and Callback function 
// prototype are same.
 
delegate void CallBackDelegate();
public static  CallBackDelegate myDelegate;

接下来,我们必须将我们的回调函数与委托关联起来

// Associating callback function with delegate
myDelegate =new MyDelegate(CallbackFunction);

好的,现在我们的函数指针已准备就绪。下一步是,我们必须将其发送到 DLL。为了将回调函数(即委托)呈现给 DLL,我们必须使用 DllImport 属性声明 SetCallBackPointer 的函数原型。 这是声明

// this function prototype should match our Custom dll’s 
// ‘SetCallBackPointer’ functioin prototype.
//
[DllImport("MyCustomDll.dll",CallingConvention=CallingConvention.StdCall)]
private static extern void SetCallBackPointer(CallBackDelegate delegate);

一切都已准备就绪;剩下的就是我们必须调用 SetCallBackPointer 函数。 以下调用将在 MyCustomDll 中调用 SetCallBackPointer 函数,并将 CallBackFunction 函数指针(委托)作为参数

SetCallBackPointer(myDelegate);

是的,我们成功了,CallBackFunction 是从我们的自定义 DLL 调用的。

从非托管 Windows 自定义 DLL 调用托管 .NET 函数。 - CodeProject - 代码之家
© . All rights reserved.