平台调用:C# 使用非托管dll函数

it2024-11-01  15

  我在学习研究WorldWind的源代码时,发现它的底层代码大量调用外部的dll,包括不同平台的DLL。也就是托管语言C#中调用非托管的dll函数。以前也遇到了这样的情况,自己只是“依猫画虎”并没深入学习和了解。现在我分几部分学习,算是弥补这一不足! 

  Interop的意思就是托管/非托管代码之间的互操作。   

 

   extern(C# 参考): http://msdn.microsoft.com/zh-cn/library/e59b22c5(VS.80).aspx

  extern 修饰符用于声明在外部实现的方法。extern 修饰符的常见用法是在使用 Interop 服务调入非托管代码时与 DllImport 属性一起使用;在这种情况下,该方法还必须声明为 static,如下面的示例所示:

  [DllImport("avifil32.dll")]  private static extern void AVIFileInit();

  将 abstract和 extern 修饰符一起使用来修改同一成员是错误的。使用 extern 修饰符意味着方法在 C# 代码的外部实现,而使用 abstract 修饰符意味着在类中未提供方法实现。

      示例:

在该示例中,程序接收来自用户的字符串并将该字符串显示在消息框中。程序使用从 User32.dll 库导入的 MessageBox 方法。

using System; using System.Runtime.InteropServices; class MainClass {    [DllImport("User32.dll")]    public static extern int MessageBox(int h, string m, string c, int type);    static int Main()    {       string myString;       Console.Write("Enter your message: ");       myString = Console.ReadLine();       return MessageBox(0, myString, "My Message Box", 0);    } }        DllImportAttribute 类: http://msdn.microsoft.com/zh-cn/library/system.runtime.interopservices.dllimportattribute(VS.80).aspx

  指示该属性化方法由非托管动态链接库 (DLL) 作为静态入口点公开。用 DllImport 属性修饰的方法必须具有static  extern 修饰符。

  命名空间:System.Runtime.InteropServices

  DllImportAttribute 属性提供对从非托管 DLL 导出的函数进行调用所必需的信息。作为最低要求,必须提供包含入口点的 DLL 的名称。可直接将此属性应用于 C# 或 C++ 方法定义;

注意 JScript 不支持此属性。可以使用 C# 或 Visual Basic 包装类从 JScript 程序访问非托管 API 方法。

    示例

下面的代码示例演示如何使用 DllImportAttribute 属性导入 Win32 MessageBox 函数。然后,代码示例将调用导入的方法。

using System; using System.Runtime.InteropServices; class Example { // Use DllImport to import the Win32 MessageBox function. [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type); static void Main() { // Call the MessageBox function using platform invoke. MessageBox(new IntPtr(0), "Hello World!", "Hello Dialog", 0); } }

    

  使用非托管 DLL 函数:http://msdn.microsoft.com/zh-cn/library/26thfadc(VS.80).aspx

  利用平台调用这种服务,托管代码可以调用在动态链接库 (DLL)(如 Win32 API 中的 DLL)中实现的非托管函数。此服务将查找并调用导出的函数,然后根据需要跨越互用边界封送其参数(整数、字符串、数组、结构等)。

      使用导出的 DLL 函数

标识 DLL 中的函数。

最低限度上,必须指定函数的名称和包含该函数的 DLL 的名称。

创建用于容纳 DLL 函数的类。

可以使用现有类,为每一非托管函数创建单独的类,或者创建包含一组相关的非托管函数的一个类。

在托管代码中创建原型。

[Visual Basic] 使用带 Function 和 Lib 关键字的 Declare 语句。在某些少见的情况下,可以使用带 Shared Function 关键字的 DllImportAttribute。这些情况在本节后面部分进行说明。

[C#] 使用 DllImportAttribute 标识 DLL 和函数。用 static 和 extern 修饰符标记方法。

[C++] 使用 DllImportAttribute 标识 DLL 和函数。用 extern "C" 标记包装方法或函数。

调用 DLL 函数。

像处理其他任何托管方法一样调用托管类上的方法。传递结构和实现回调函数属于特殊情况。  

  利用平台调用,可以通过调用 Win32 API 和其他 DLL 中的函数来控制操作系统中相当大的一部分。除了 Win32 API 之外,还有许多其他的 API 和 DLL 可通过平台调用来调用。

下表将说明 Win32 API 中几个常用的 DLL。

DLL 内容说明

GDI32.dll

用于设备输出的图形设备接口 (GDI) 函数,例如用于绘图和字体管理的函数。

Kernel32.dll

用于内存管理和资源处理的低级别操作系统函数。

User32.dll

用于消息处理、计时器、菜单和通信的 Windows 管理函数。

 

         

  平台调用示例:http://msdn.microsoft.com/zh-cn/library/42b9ea93(VS.80).aspx

下面的示例将说明如何定义和调用 User32.dll 中的 MessageBox 函数,并将简单字符串当作参数进行传递。在这些示例中,DllImportAttribute.CharSet Field 字段设置为 Auto,以便让目标平台确定字符宽度和字符串封送处理。

C#

using System.Runtime.InteropServices; public class Win32 { [DllImport("user32.dll", CharSet=CharSet.Auto)] public static extern IntPtr MessageBox(int hWnd, String text, String caption, uint type); } public class HelloWorld { public static void Main() { Win32.MessageBox(0, "Hello World", "Platform Invoke Sample", 0); } } C++ using namespace System::Runtime::InteropServices; typedef void* HWND; [DllImport("user32", CharSet=CharSet::Auto)] extern "C" IntPtr MessageBox(HWND hWnd, String* pText, String* pCaption, unsigned int uType); void main(void) { String* pText = L"Hello World!"; String* pCaption = L"Platform Invoke Sample"; MessageBox(0, pText, pCaption, 0); }

 

 

转载于:https://www.cnblogs.com/wuhenke/archive/2009/12/09/1620599.html

相关资源:在VS2010上使用C#调用非托管C++生成的DLL文件
最新回复(0)