zoukankan      html  css  js  c++  java
  • 平台调用:C# 使用非托管dll函数

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

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

     

      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 类:

      指示该属性化方法由非托管动态链接库 (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 函数

    1. 标识 DLL 中的函数

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

    2. 创建用于容纳 DLL 函数的类

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

    3. 在托管代码中创建原型

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

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

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

    4. 调用 DLL 函数

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

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

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

    DLL 内容说明

    GDI32.dll

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

    Kernel32.dll

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

    User32.dll

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

             

    下面的示例将说明如何定义和调用 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);
    }


     

  • 相关阅读:
    0102-进程操作(面向对象简单工厂模式,打开输入文件)
    0101-进程操作(变量命名)
    win10无法成功完成操作因为文件包含病毒或潜在的垃圾软件如何处理
    序列化和反序列化
    __slot__的用法
    python中typeguard包
    pandas如何将多个DataFrame写入同一个excel工作簿中
    DEAP库遗传算法
    【教程】如何把喜马拉雅音频下载到电脑
    oracle安装路径查看方式
  • 原文地址:https://www.cnblogs.com/wuhenke/p/1620599.html
Copyright © 2011-2022 走看看