namespace Wintellect.Interop.Sound
{
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
sealed class Sound
{
public static void MessageBeep(BeepTypes type)
{
if(!MessageBeep((UInt32) type))
{
Int32 err = Marshal.GetLastWin32Error();
throw new Win32Exception(err);
}
} [DllImport("User32.dll", SetLastError=true)]
static extern Boolean MessageBeep(UInt32 beepType); private Sound()
{
}
} enum BeepTypes{
Simple = -,
Ok = 0x00000000,
IconHand = 0x00000010,
IconQuestion = 0x00000020,
IconExclamation = 0x00000030,
IconAsterisk = 0x00000040
}
}

C 和 Win32 的一些公共数据类型及其规范,以及一个具有匹配规范的公共语言运行库类型

Win32 Types Specification CLR Type
char, INT8, SBYTE, CHAR† 8-bit signed integer System.SByte
short, short int, INT16, SHORT 16-bit signed integer System.Int16
int, long, long int, INT32, LONG32, BOOL†, INT 32-bit signed integer System.Int32
__int64, INT64, LONGLONG 64-bit signed integer System.Int64
unsigned char, UINT8, UCHAR†, BYTE 8-bit unsigned integer System.Byte
unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR†, __wchar_t 16-bit unsigned integer System.UInt16
unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT 32-bit unsigned integer System.UInt32
unsigned __int64, UINT64, DWORDLONG, ULONGLONG 64-bit unsigned integer System.UInt64
float, FLOAT Single-precision floating point System.Single
double, long double, DOUBLE Double-precision floating point System.Double
†In Win32 this type is an integer with a specially assigned meaning; in contrast, the CLR provides a specific type devoted to this meaning.

在 C# 中通过 P/Invoke 调用Win32 DLL

Calling Win32 DLLs in C# with P/Invoke

指针参数

指针增加了封送数据的复杂性,因为它们增加了一个间接层。使用托管代码表示此附加间接层的方式有多种。

FileEncryptionStatus API 函数

BOOL FileEncryptionStatus(
LPCTSTR lpFileName, // file name
LPDWORD lpStatus // encryption status
);

工作方式是调用程序向该函数传递指向一个 DWORD 变量的指针,而该 API 函数用状态值填充指向的内存位置。

调用非托管 FileEncryptionStatus 函数的可能外部方法定义:

[DllImport("Advapi32.dll", CharSet=CharSet.Auto)]
static extern Boolean FileEncryptionStatus(String filename, out UInt32 status);

该定义使用 out 关键字来为 UInt32 状态值指示 by-ref 参数。这里我也可以选择 ref 关键字,实际上在运行时会产生相同的机器码。out 关键字只是一个 by-ref 参数的规范,它向 C# 编译器指示所传递的数据只在被调用的函数外部传递。相反,如果使用 ref 关键字,则编译器会假定数据可以在被调用的函数的内部和外部传递。

(The definition uses the out keyword to indicate a by-ref parameter for the UInt32 status value. I could have selected the ref keyword here as well, and in fact both result in the same machine code at run time. The out keyword is simply a specialization of a by-ref parameter that indicates to the C# compiler that the data being passed is only being passed out of the called function. In contrast, with the ref keyword the compiler assumes that data may flow both in and out of the called function.)

封送不透明 (Opaque) 指针:一种特殊情况

当一个不透明指针返回给您的应用程序(或者您的应用程序期望得到一个不透明指针)时,您应该将参数或返回值封送为 CLR 中的一种特殊类型 — System.IntPtr。

请记住,任何返回或接受句柄的 API 函数其实操作的就是不透明指针。您的代码应该将 Windows 中的句柄封送成 System.IntPtr 值。

当使用 Windows API 函数时,因为指针应是不透明的,所以除了存储和传递给外部方法外,不能将它们另做它用。

这种“只限存储和传递”规则的两个特例是当您需要向外部方法传递 null 指针值和需要比较 IntPtr 值与 null 值的情况。为了做到这一点,您不能将零强制转换为 System.IntPtr,而应该在 IntPtr 类型上使用 Int32.Zero 静态公共字段,以便获得用于比较或赋值的 null 值。

封送文本

  • 是您的应用程序向 API 函数传递文本数据,还是 API 函数向您的应用程序返回字符串数据?或者二者兼有?

  • 您的外部方法应该使用什么托管类型?

  • API 函数期望得到的是什么格式的非托管字符串?

UINT_PTR SHAppBarMessage(
_In_ DWORD dwMessage,
_Inout_ PAPPBARDATA pData
);
typedef struct _AppBarData {
DWORD cbSize;
HWND hWnd;
UINT uCallbackMessage;
UINT uEdge;
RECT rc;
LPARAM lParam;
} APPBARDATA, *PAPPBARDATA;
typedef struct _RECT {
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT, *PRECT;
struct AppBarData
{
public UInt32 cbSize; public IntPtr hWnd; public UInt32 uCallbackMessage; public UInt32 uEdge; public AppBarRect rc; public IntPtr lParam;
} struct AppBarRect
{
public Int32 left; public Int32 top; public Int32 right; public Int32 bottom;
}

DLLImport的更多相关文章

  1. dll导入导出宏定义,出现“不允许 dllimport 函数 的定义”的问题分析

    建立dll项目后,在头文件中,定义API宏 #ifndef API_S_H #define API_S_H ...... #ifndef DLL_S_20160424 #define API _dec ...

  2. VC++ : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::basic_string<wchar_t,struct std::char_traits<wchar_t>

    最近学习Google Breakpad,将其用在了自己的项目中,编译的版本为VS2010,没有什么问题.但是为了和之前的程序兼容,需要使用VS2008版本的程序,于是又编译了VS2008版本的代码,但 ...

  3. 用DllImport引用的外部DLL文件如何通过clickonce发布

    在.net中非托管代码或非COM组件的外部DLL文件只能用DllImport的方式使用,但是在clickonce方式发布时不会自动包含到发布清单中去,办法是在项目中先把外部DLL文件作为普通文件添加进 ...

  4. 《程序员的自我修养》读书笔记 - dllimport

    Math.c  { __declspec (dllexport)  double Add (xx, xx) {...}} MathApp.c  { __declspec(dllimport) doub ...

  5. 关于C#使用Dllimport 导入vc++动态库后网站部署提示 “无法加载 DLL,找不到指定模块”的解决方法。

    这次项目需要,做了一个C#写的WebService服务给外部调用,服务内部引用了算法库,本地调试已经通过,现场部署服务时各种提示找不到DLL文件. 第一.如果是包含有32位库在64位服务器系统上运行, ...

  6. c# 利用动态库DllImport("kernel32")读写ini文件(提供Dmo下载)

    c# 利用动态库DllImport("kernel32")读写ini文件 自从读了设计模式,真的会改变一个程序员的习惯.我觉得嘛,经验也可以从一个人的习惯看得出来,看他的代码编写习 ...

  7. C# DllImport“调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配 ”

    调用外部dll时,出现如下问题 C# DllImport“调用导致堆栈不对称.原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配.请检查 PInvoke 签名的调用约定和参数与非托管的目标 ...

  8. DllImport attribute的总结

    C#有没有方法可以直接都用已经存在的功能(比如Windows中的一些功能,C++中已经编写好的一些方法),而不需要重新编写代码? 答案是肯定,就是通过接下来要说的 DllImport . DllImp ...

  9. c#的dllimport使用方法详解,调试找不到dll的方法

    DllImport会按照顺序自动去寻找的地方: 1.exe所在目录 2.System32目录 3.环境变量目录所以只需要你把引用的DLL 拷贝到这三个目录下 就可以不用写路径了 或者可以这样serve ...

  10. C# DllImport用法和路径问题

    DllImport是System.Runtime.InteropServices命名空间下的一个属性类,其功能是提供从非托管DLL导出的函数的必要调用信息.    DllImport属性应用于方法,要 ...

随机推荐

  1. 认识FiddlerScript

    FiddlerScript 是Fiddler 的一项非常强大的功能,它允许你增强Fiddler UI,添加新的特性,修改请求与响应内容等等... 1.编写FiddlerScript FiddlerSc ...

  2. Nagios3完整配置文档

    第一章:简单快速安装nagios 1.1 准备软件包 在做安装之前确认要对该机器拥有root权限. 确认你安装好的linux系统上已经安装如下软件包再继续. Apache GCC编译器 GD库与开发库 ...

  3. MySQL提示:The server quit without updating PID file问题的解决办法

    错误如下: [root@snsgou mysql]# service mysql restartMySQL server PID file could not be found![失败]Startin ...

  4. 移动wabAPP 开发 viewport 注意事项

    我们在开发移动设备的网站时,最常见的的一个动作就是把下面这个东西复制到我们的head标签中: <meta name="viewport" content="widt ...

  5. ThinkPHP下隐藏index.php以及URL伪静态

    第一种方法: 设置url的重写模式(默认模式是1) 'URL_MODEL' => 2, // URL访问模式,可选参数0.1.2.3,代表以下四种模式: 第二种方法:  使用Apache来进行设 ...

  6. Qt之启动外部程序(调用cmd.exe ping putty winscp 管道等等,比较牛叉)

    http://blog.csdn.net/u011012932/article/details/50478833

  7. Microsoft SQL Server 2012 数据库安装图解教程

    本文部分引用以下文章: SQL Server 2012 安装图解教程(附sql2012下载地址)_MsSql_脚本之家 http://www.jb51.net/article/36049.htm SQ ...

  8. LinkedList源代码深入剖析

    第1部分 LinkedList介绍LinkedList简介 public class LinkedList<E> extends AbstractSequentialList<E&g ...

  9. oracle时间加减的语句写法

    FROM: http://soft.doit.com.cn/article/2012/0105/2850851.shtml --加法 --加1年  SELECT SYSDATE,ADD_MONTHS( ...

  10. bzoj3170

    以前写的,好像忘写解题报告 注意是一个跟曼哈顿距离很有用的结论 |xi-xj|+|yi-yj|=max(|xi+yi-(xj+yj)|,|xi-yi+(xj-yj)|) 因为绝对值有个性质是|a-b| ...