从C#程序中调用非受管DLLs的方法

前端技术 2023/09/07 C#

本文实例讲述了从C#程序中调用非受管DLLs的方法。分享给大家供大家参考。具体方法如下:

前言:

从所周知,.NET已经渐渐成为一种技术时尚,那么C#很自然也成为一种编程时尚。如何利用浩如烟海的Win32 API以及以前所编写的 Win32 代码已经成为越来越多的C#程序员所关注的问题。本文将介绍如何从C#代码中调用非受管DLLs。如果某个函数是一个带有串类型(char*)输出参数的Win32 API 或者是DLL输出函数,那么从C#中如何调用它呢?对于输入参数的情形问题到不大,但如何获取从参数中返回的串呢?此外,如何调用有结构(struct)和回调(callback)作为参数的函数,如GetWindowsRect 和EnumWindows?那我们又如何将参数从C++和MFC中转换成C# 所要的类型呢?下面就让我们来一一解决这些问题。

微软.NET的一个最主要的优势是它提供一个语言无关的开发系统。我们可以用Visual Basic、C++、C#等等语言来编写类,然后在其它语言中使用,我们甚至可以用不同的语言来派生类。但是如何调用以前开发的非受管DLL呢?方法是必须将.NET对象转化成结构、char*以及C语言的指针。用行话说就是参数必须被列集(marshal)。说到列集,用一两句话也说不清楚。所幸的是实现列集并不要我们知道太多的东西。

为了从C# 中调用DLL函数,首先必须要有一个声明,就象长期以来使用Visual Basic的程序员所做的那样,只不过在C#中使用的是DllImport关键字:

复制代码 代码如下:
using System.Runtime.InteropServices; // DllImport所在的名字空间
public class Win32 {
  [DllImport(\"User32.Dll\")]
  public static extern void SetWindowText(int h, String s);
}

在C#中,DllImport关键字作用是告诉编译器入口点在哪里,并将打包函数捆绑在一个类中。我们可以为这类取任何名字,这里不妨将类名取为 Win32。我们甚至可以将这个类放到一个名字空间中,就象下面的代码这样:

Win32API.cs 源代码

复制代码 代码如下:
// Win32API: 此为名字空间,打包所选的Win32 API 函数
// 编译方法:
//    csc /t:library /out:Win32API.dll Win32API.cs
//
using System;
using System.Drawing;
using System.Text;
using System.Runtime.InteropServices;

/////////////////////////////////////////////////////////////////
// 包装Win32 API函数的名字空间。想用哪个Win32 API,往里添加即可。
//
namespace Win32API {
   [StructLayout(LayoutKind.Sequential)]
   public struct POINT {
      public POINT(int xx, int yy) { x=xx; y=yy; }
      public int x;
      public int y;
      public override string ToString() {
         String s = String.Format(\"({0},{1})\", x, y);
         return s;
      }
   }

   [StructLayout(LayoutKind.Sequential)]
   public struct SIZE {
      public SIZE(int cxx, int cyy) { cx=cxx; cy=cyy; }
      public int cx;
      public int cy;
      public override string ToString() {
         String s = String.Format(\"({0},{1})\", cx, cy);
         return s;
      }
   }

   [StructLayout(LayoutKind.Sequential)]
   public struct RECT {
      public int left;
      public int top;
      public int right;
      public int bottom;
      public int Width()      { return right - left; }
      public int Height()     { return bottom - top; }
      public POINT TopLeft()  { return new POINT(left,top); }
      public SIZE  Size()     { return new SIZE(Width(), Height()); }
      public override string ToString() {
         String s = String.Format(\"{0}x{1}\", TopLeft(), Size());
         return s;
      }
   }

   public class Win32 {
      [DllImport(\"user32.dll\")]
      public static extern bool IsWindowVisible(int hwnd);

      [DllImport(\"user32.dll\")]
      public static extern int GetWindowText(int hwnd,
         StringBuilder buf, int nMaxCount);

      [DllImport(\"user32.dll\")]
      public static extern int GetClassName(int hwnd,
         [MarshalAs(UnmanagedType.LPStr)] StringBuilder buf,
         int nMaxCount);

      [DllImport(\"user32.dll\")]
      public static extern int GetWindowRect(int hwnd, ref RECT rc);

      [DllImport(\"user32.dll\")]
      // 注意,运行时知道如何列集一个矩形
      public static extern int GetWindowRect(int hwnd, ref Rectangle rc);
   }
}

本文地址:https://www.stayed.cn/item/17924

转载请注明出处。

本站部分内容来源于网络,如侵犯到您的权益,请 联系我

我的博客

人生若只如初见,何事秋风悲画扇。