迎接离开通宝tb888网! | 资助中央 通宝tb888beatahowe.com美如初恋!
通宝tb888网

创立Win32 DLL--并在C#内中挪用

2014-07-14 21:26 | 人气:1416

这是三篇网上搜集的技艺文章的合集,区分化说了如何创立Win32 DLL,然后如何在C#内中挪用这个DLL的教程。

首先是创立Win32 DLL的文章。解嗣魅这个的文章四处都有,这里给出一篇我看过的:http://www.flipcode.com/articles/article_creatingdlls.shtml。Win32 DLL的创立着真实Visual Studio内中曾经给出了比照好的模板,只是需求细致的,有些XXX_API宏并没有把extern "C"加出来,何等会构成在C#内中找不到这个函数的错误。所以,请记着,必定要把函数界说extern "C"。




第二篇文章来之于http://edu.100down.com/it/program/Csharp/105256797.html,下面是转贴内容:

平台挪用办事 (PInvoke) 允许托管代码挪用在 DLL 中实现的非托管函数。

本教程说明应用什么方法才干从 C# 挪用非托管 DLL 函数。该教程所批判争辩的属性允许你挪用这些函数并使数据模范掉掉准确封送。

教程

C# 代码有以下两种可以直接挪用非托管代码的方法:

  • 直接挪用从 DLL 导出的函数。

  • 挪用 COM 器械上的接口方法(有关更多信息,请拜见 COM Interop 第一局部:C# 客户端教程)。

关于这两种技艺,都必需向 C# 编译器供应非托管函数的声明,而且还大约需求向 C# 编译器供应如何封送与非托管代码之间转达的参数跟前往值的说明。

该教程由下列主题组成:

  • 直接从 C# 挪用 DLL 导出

  • 默认封送处置处分跟为非托管方法的参数指定自界说封送处置处分

  • 为用户界说的构造指定自界说封送处置处分

  • 注册回调方法

该教程包含下列示例:

  • 示例 1 应用 DllImport

  • 示例 2 重写默认封送处置处分

  • 示例 3 指定自界说封送处置处分

直接从 C# 挪用 DLL 导出

若要声明一个方法使其存在来自 DLL 导出的实现,请实行下列支配:

  • 应用 C# 关键字 static 跟 extern 声明方法。

  • 将 DllImport 属性附加到该方法。DllImport 属性允许你指定包含该方法的 DLL 的名称。素日的做法是用与导出的方法相同的名称命名 C# 方法,但也可以对 C# 方法应用差异的名称。

  • 还可以为方法的参数跟前往值指定自界说封送处置处分信息,这将重写 .NET Framework 的默认封送处置处分。

示例 1

本示例表现如何应用 DllImport 属性经过挪用 msvcrt.dll 中的 puts 输入音讯。

// PInvokeTest.cs
using System;
using System.Runtime.InteropServices;

class PlatformInvokeTest
{
    [DllImport("msvcrt.dll")]
    public static extern int puts(string c);
    [DllImport("msvcrt.dll")]
    internal static extern int _flushall();

    public static void Main() 
    {
        puts("Test");
        _flushall();
    }
}

输入

Test

代码批判争辩

前面的示例表现了声明在非托管 DLL 中实现的 C# 方法的最低央求。PlatformInvokeTest.puts 方法用 static 跟 extern 修饰符声明而且存在 DllImport 属性,该属性应用默认名称 puts 照顾编译器此实现来自msvcrt.dll。若要对 C# 方法应用差异的名称(如 putstring),则必需在 DllImport 属性中应用 EntryPoint 选项,如下所示:

[DllImport("msvcrt.dll", EntryPoint="puts")]

有关 DllImport 属性的语法的更多信息,请拜见 DllImportAttribute 类。

默认封送处置处分跟为非托管方法的参数指定自界说封送处置处分

当从 C# 代码中挪用非托管函数时,群众言语运行库必需封送参数跟前往值。

关于每个 .NET Framework 模范均有一个默认非托管模范,群众言语运行库将应用此非托管模范在托管到非托管的函数挪用中封送数据。好比,C# 字符串值的默认封送处置处分是封送为 LPTSTR(指向 TCHAR 字符缓冲区的指针)模范。可以在非托管函数的 C# 声明中应用 MarshalAs 属性重写默认封送处置处分。

示例 2

本示例应用 DllImport 属性输入一个字符串。它还表现如何经过应用 MarshalAs 属性重写函数参数的默认封送处置处分。

// Marshal.cs
using System;
using System.Runtime.InteropServices;

class PlatformInvokeTest
{
    [DllImport("msvcrt.dll")]
    public static extern int puts(
        [MarshalAs(UnmanagedType.LPStr)]
        string m);
    [DllImport("msvcrt.dll")]
    internal static extern int _flushall();


    public static void Main() 
    {
        puts("Hello World!");
        _flushall();
    }
}

输入

运行此示例时,字符串

Hello World!

将表现在控制台上。

代码批判争辩

在前面的示例中,puts 函数的参数的默认封送处置处分已从默认值 LPTSTR 重写为 LPSTR。

MarshalAs 属性可以安排在方法参数、方法前往值以及结会谈类的字段上。若要设备方法前往值的封送处置处分,请将 MarshalAs 属性与前往属性位置重写一同安排在方法上的属性块中。好比,若要显式设备puts 方法前往值的封送处置处分:

...
[DllImport("msvcrt.dll")] 
[return : MarshalAs(UnmanagedType.I4)]
public static extern int puts( 
...

有关 MarshalAs 属性的语法的更多信息,请拜见 MarshalAsAttribute 类。

细致   In 跟 Out 属性可用于疏解非托管方法的参数。它们与 MIDL 源文件中的 in 跟 out 修饰符的变乱措施相同。请细致,Out 属性与 C# 参数修饰符 out 差异。有关 In 跟 Out 属性的更多信息,请拜见 InAttribute 类跟 OutAttribute 类。

为用户界说的构造指定自界说封送处置处分

可以为转抵达非托管函数或从非托管函数前往的结会谈类的字段指定自界说封送处置处分属性。经过向构造或类的字段中增加 MarshalAs 属性可以做到这一点。还必需应用 StructLayout 属性设备构造的构造,还可以控制字符串成员的默认封送处置处分,并设备默认封装年夜小。

示例 3

本示例说明如何为构造指定自界说封送处置处分属性。

请思索下面的 C 构造:

typedef struct tagLOGFONT 
{ 
   LONG lfHeight; 
   LONG lfWidth; 
   LONG lfEscapement; 
   LONG lfOrientation; 
   LONG lfWeight; 
   BYTE lfItalic; 
   BYTE lfUnderline; 
   BYTE lfStrikeOut; 
   BYTE lfCharSet; 
   BYTE lfOutPrecision; 
   BYTE lfClipPrecision; 
   BYTE lfQuality; 
   BYTE lfPitchAndFamily; 
   TCHAR lfFaceName[LF_FACESIZE]; 
} LOGFONT;

在 C# 中,可以应用 StructLayout 跟 MarshalAs 属性描写前面的构造,如下所示:

// logfont.cs
// compile with: /target:module
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public class LOGFONT 
{ 
    public const int LF_FACESIZE = 32;
    public int lfHeight; 
    public int lfWidth; 
    public int lfEscapement; 
    public int lfOrientation; 
    public int lfWeight; 
    public byte lfItalic; 
    public byte lfUnderline; 
    public byte lfStrikeOut; 
    public byte lfCharSet; 
    public byte lfOutPrecision; 
    public byte lfClipPrecision; 
    public byte lfQuality; 
    public byte lfPitchAndFamily;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=LF_FACESIZE)]
    public string lfFaceName; 
}

有关 StructLayout 属性的语法的更多信息,请拜见 StructLayoutAttribute 类。

然后即可将该构造用在 C# 代码中,如下所示:

// pinvoke.cs
// compile with: /addmodule:logfont.netmodule
using System;
using System.Runtime.InteropServices;
 
class PlatformInvokeTest
{   
      [DllImport("gdi32.dll", CharSet=CharSet.Auto)]
      public static extern IntPtr CreateFontIndirect(
            [In, MarshalAs(UnmanagedType.LPStruct)]
            LOGFONT lplf   // characteristics
            );
 
      [DllImport("gdi32.dll")]
      public static extern bool DeleteObject(
            IntPtr handle
            );
 
      public static void Main() 
      {
            LOGFONT lf = new LOGFONT();
            lf.lfHeight = 9;
            lf.lfFaceName = "Arial";
            IntPtr handle = CreateFontIndirect(lf);
 
            if (IntPtr.Zero == handle)
            {
                  Console.WriteLine("Can't creates a logical font.");
            }
            else
            {
                  
                  if (IntPtr.Size == 4)
                        Console.WriteLine("{0:X}", handle.ToInt32());
                  else
                        Console.WriteLine("{0:X}", handle.ToInt64());         

                  // Delete the logical font created.
                  if (!DeleteObject(handle))
                       Console.WriteLine("Can't delete the logical font");
            }
      }
}

运行示例

C30A0AE5

代码批判争辩

在前面的示例中,CreateFontIndirect 方法应用了一个 LOGFONT 模范的参数。MarshalAs 跟 In 属性用于限制此参数。措施将由此方法前往的数值表现为十六进制年夜写字符串。

注册回调方法

若要注册挪用非托管函数的托管回调,请用相同的参数列表声明一个拜托并经过 PInvoke 转达它的一个实例。在非托管端,它将表现为一个函数指针。有关 PInvoke 跟回调的更多信息,请拜见平台挪用详解。

好比,思索以下非托管函数 MyFunction,此函数央求 callback 作为其参数之一:

typedef void (__stdcall *PFN_MYCALLBACK)();
int __stdcall MyFunction(PFN_ MYCALLBACK callback);

若要从托管代码挪用 MyFunction,请声明该拜托,将 DllImport 附加到函数声明,并依据需求封送任何参数或前往值:

public delegate void MyCallback();
[DllImport("MYDLL.DLL")]
public static extern void MyFunction(MyCallback callback);

同时,请确保拜托实例的生涯期突围非托管代码的生涯期;否则,拜托在经过剩余采用后将不再可用。




 第三篇文章来之于http://www.njpro.cn/8918/ShowPost.aspx,一篇关于C/C++跟C#中的数据模范的对应表。


Wtypes.h 中的非托管模范非托管 C 言语模范托管类名说明
HANDLEvoid*System.IntPtr32 位
BYTEunsigned charSystem.Byte8 位
SHORTshortSystem.Int1616 位
WORDunsigned shortSystem.UInt1616 位
INTintSystem.Int3232 位
UINTunsigned intSystem.UInt3232 位
LONGlongSystem.Int3232 位
BOOLlongSystem.Int3232 位
DWORDunsigned longSystem.UInt3232 位
ULONGunsigned longSystem.UInt3232 位
CHARcharSystem.Char用 ANSI 修饰。
LPSTRchar*System.String 或System.StringBuilder用 ANSI 修饰。
LPCSTRConst char*System.String 或System.StringBuilder用 ANSI 修饰。
LPWSTRwchar_t*System.String 或System.StringBuilder用 Unicode 修饰。
LPCWSTRConst wchar_t*System.String 或System.StringBuilder用 Unicode 修饰。
FLOATFloatSystem.Single32 位
DOUBLEDoubleSystem.Double64 位


关于咱们 - 网站声明 - 网站地图 - 资本地图 - 友谊链接 - 网站客服 - 联络咱们

网站客服QQ:2846424093    通宝tb888上传用户QQ群:460291265   

[email protected] 2016-2018  beatahowe.com 网站版权全部   

备案号:苏ICP备12009002号-5