若要声明一个方法使其具有来自 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();}
}

C#入门教程:C# 使用DllImport 调用 native DLL的方法
更多
c#入门教程c#DllImport

若要声明一个方法使其具有来自 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());elseConsole.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);

同时,请确保委托实例的生存期覆盖非托管代码的生存期;否则,委托在经过垃圾回收后将不再可用。

C# 使用DllImport 调用 native DLL的方法相关推荐

  1. C# 制作Com组件:java调用.net DLL的方法

    本文将详细为大家介绍一个java调用.net DLL的方法,以实现特殊的客户的特殊要求:"在Java项目中必须使用其提供的用.net写的DLL加密机制!" 环境与工具: ◆.net ...

  2. c#调用c语言的自定义函数,[转]在C#中调用C语言函数(静态调用Native DLL,Windows Microsoft.Net平台)...

    对于不太了解.Net的人,如果想要了解.Net,我必须给他介绍P/Invoke.P/Invoke是什么呢?简单地说,就是在.Net中调用本地代码(Native code)的一种解决方案.所谓" ...

  3. java调用C++ DLL库方法

    转载地址: https://www.cnblogs.com/xiaocainiao2hao/p/5619862.html 最近一个项目要开发网页端人脸识别项目,人脸识别的算法已经写好,是C++版,但是 ...

  4. C# 调用 Delphi Dll链接库方法及示例

    每种编程语言调用DLL的方法都不尽相同,在此只对用C#调用Delphi DLL的方法进行介绍 首先要搞清楚一点的是:什么是托管,什么是非托管? 一般可以认为:非托管代码主要是基于win 32平台开发的 ...

  5. qt采用C++/CLI 方式调用C#dll的封装方法

    在qt中调用C++dll一般都可以直接使用,但是在调用C#版dll时,就有些麻烦了.本文采用C++/cli封装C#的dll的方式.实现了qt调用C#dll的方法. .h文件 #pragma once ...

  6. c#调用外部dll详解

     一.      DLL与应用程序 动态链接库(也称为DLL,即为"Dynamic Link Library"的缩写)是Microsoft Windows最重要的组成要素之一, ...

  7. 非常好的dllimport 文章--在 C# 中通过 P/Invoke 调用Win32 DLL

    http://msdn.microsoft.com/zh-cn/library/aa686045.aspx 在 C# 中通过 P/Invoke 调用Win32 DLL 发布日期 : 1/13/2005 ...

  8. c调用其他类的方法_Java 的 Native 方法——今天又进步了

    1. 简介 1.1 个人理解 初次遇见 native 是在 java.lang.String 源码中的一个 intern 方法: public native String intern(); 因为还是 ...

  9. c# 调用c++DLL方法及注意事项

    引用命名空间 using System.Runtime.InteropServices 调用方法: 一.静态加载 用DllImprot方式来加载c++DLL.如下格式: //对应c++方法//void ...

最新文章

  1. my.cnf mysqld mysql_MySQL配置文件my.cnf详解【mysqld】模块(二)
  2. 微信/QQ 中已停止访问该网页的处理办法
  3. ubuntu 14.04 安装qq 2015
  4. MariaDB:删除数据库报错:error: 'Error dropping database (can't rmdir './shiro', errno: 39)'
  5. 【图像处理基础知识】python+opencv显示中文
  6. NOX+ Open vSwitch安装相关命令【备份】
  7. 热门用户推荐能否支持分类筛选?
  8. 避免野指针的方法及结构体小细节
  9. 每日一技|巧用 Telnet 调试 Dubbo 服务
  10. 阿里巴巴Java开发文档2020版学习-代码格式
  11. 服务器TPMC值计算
  12. 宽高变化动画代码,旋转动画代码(HTML5)
  13. 面试常见的26个问题
  14. linux fedora 24 使用 ibus 智能拼音 输入 补全 英文
  15. Data-free量化
  16. new Integer()与 Integer.valueOf()区别和联系
  17. kali linux怎么远程桌面,适用于kali linux的远程桌面开启方法(从windows xp 远程登录到kali linux )...
  18. 收藏!5款超级好用的小工具推荐,各个都是同类软件中的翘楚
  19. halcon 直线测量
  20. 评论留言用html怎么做,利用JS实现评论留言发布表单代码

热门文章

  1. 电脑桌面云便签怎么在分类标签中清除内容?
  2. [RISC-V MCU 应用开发]基于CH32V307和TtencentOS Tiny的物联网心率监测
  3. 压缩感知重构算法综述-学习笔记
  4. 离散KL变换原理、实例以及matlab实现
  5. 基于stm32单片机有害气体监测检测Proteus仿真
  6. Unity FFT海水渲染效果展示
  7. 仿蘑菇街,京东,苏宁易购,海尔商城等33套大气购物商城网站模板,附源码免费下载地址...
  8. java cleartype_等宽雅黑宋体2.1(支持ClearType和GDI++)
  9. A+CLUB活动预告 | 2023年5月
  10. 报关单上常出现的英文单词缩写