C# 程序员参考--平台调用教程
2007-10-10 09:00
411 查看
平台调用服务 (PInvoke) 允许托管代码调用在 DLL 中实现的非托管函数。
本教程说明使用什么方法才能从 C# 调用非托管 DLL 函数。该教程所讨论的属性允许您调用这些函数并使数据类型得到正确封送。
直接调用从 DLL 导出的函数。
调用 COM 对象上的接口方法(有关更多信息,请参见 COM Interop 第一部分:C# 客户端教程)。
对于这两种技术,都必须向 C# 编译器提供非托管函数的声明,并且还可能需要向 C# 编译器提供如何封送与非托管代码之间传递的参数和返回值的说明。
该教程由下列主题组成:
直接从 C# 调用 DLL 导出
默认封送处理和为非托管方法的参数指定自定义封送处理
为用户定义的结构指定自定义封送处理
注册回调方法
该教程包括下列示例:
示例 1 使用 DllImport
示例 2 重写默认封送处理
示例 3 指定自定义封送处理
使用 C# 关键字 static 和 extern 声明方法。
将 DllImport 属性附加到该方法。DllImport 属性允许您指定包含该方法的 DLL 的名称。通常的做法是用与导出的方法相同的名称命名 C# 方法,但也可以对 C# 方法使用不同的名称。
还可以为方法的参数和返回值指定自定义封送处理信息,这将重写 .NET Framework 的默认封送处理。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
// PInvokeTest.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System.Runtime.InteropServices;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class PlatformInvokeTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[DllImport("msvcrt.dll")]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static extern int puts(string c);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[DllImport("msvcrt.dll")]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
internal static extern int _flushall();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static void Main()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
puts("Test");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
_flushall();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
输出
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
Test
代码讨论
前面的示例显示了声明在非托管 DLL 中实现的 C# 方法的最低要求。
有关 DllImport 属性的语法的更多信息,请参见 DllImportAttribute 类。
对于每个 .NET Framework 类型均有一个默认非托管类型,公共语言运行库将使用此非托管类型在托管到非托管的函数调用中封送数据。例如,C# 字符串值的默认封送处理是封送为 LPTSTR(指向 TCHAR 字符缓冲区的指针)类型。可以在非托管函数的 C# 声明中使用 MarshalAs 属性重写默认封送处理。
在前面的示例中,
MarshalAs 属性可以放置在方法参数、方法返回值以及结构和类的字段上。若要设置方法返回值的封送处理,请将 MarshalAs 属性与返回属性位置重写一起放置在方法上的属性块中。例如,若要显式设置
有关 MarshalAs 属性的语法的更多信息,请参见 MarshalAsAttribute 类。
注意 In 和 Out 属性可用于批注非托管方法的参数。它们与 MIDL 源文件中的 in 和 out 修饰符的工作方式类似。请注意,Out 属性与 C# 参数修饰符 out 不同。有关 In 和 Out 属性的更多信息,请参见 InAttribute 类和 OutAttribute 类。
请考虑下面的 C 结构:
在 C# 中,可以使用 StructLayout 和 MarshalAs 属性描述前面的结构,如下所示:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
// logfont.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
// compile with: /target:module
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System.Runtime.InteropServices;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
[StructLayout(LayoutKind.Sequential)]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
public class LOGFONT
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public const int LF_FACESIZE = 32;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public int lfHeight;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public int lfWidth;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public int lfEscapement;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public int lfOrientation;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public int lfWeight;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfItalic;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfUnderline;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfStrikeOut;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfCharSet;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfOutPrecision;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfClipPrecision;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfQuality;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfPitchAndFamily;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=LF_FACESIZE)]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public string lfFaceName;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
有关 StructLayout 属性的语法的更多信息,请参见 StructLayoutAttribute 类。
然后即可将该结构用在 C# 代码中,如下所示:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
// pinvoke.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
// compile with: /addmodule:logfont.netmodule
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System.Runtime.InteropServices;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class PlatformInvokeTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[DllImport("gdi32.dll", CharSet=CharSet.Auto)]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static extern IntPtr CreateFontIndirect(
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[In, MarshalAs(UnmanagedType.LPStruct)]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
LOGFONT lplf // characteristics
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[DllImport("gdi32.dll")]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static extern bool DeleteObject(
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
IntPtr handle
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static void Main()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
LOGFONT lf = new LOGFONT();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
lf.lfHeight = 9;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
lf.lfFaceName = "Arial";
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
IntPtr handle = CreateFontIndirect(lf);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
if (IntPtr.Zero == handle)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine("Can't creates a logical font.");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
else
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
if (IntPtr.Size == 4)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine("{0:X}", handle.ToInt32());
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
else
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine("{0:X}", handle.ToInt64());
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
// Delete the logical font created.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
if (!DeleteObject(handle))
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine("Can't delete the logical font");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}运行示例
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
C30A0AE5
代码讨论
在前面的示例中,
例如,考虑以下非托管函数
若要从托管代码调用
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
public delegate void MyCallback();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
[DllImport("MYDLL.DLL")]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
public static extern void MyFunction(MyCallback callback);
同时,请确保委托实例的生存期覆盖非托管代码的生存期;否则,委托在经过垃圾回收后将不再可用。
本教程说明使用什么方法才能从 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输出消息。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
// PInvokeTest.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System.Runtime.InteropServices;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class PlatformInvokeTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[DllImport("msvcrt.dll")]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static extern int puts(string c);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[DllImport("msvcrt.dll")]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
internal static extern int _flushall();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static void Main()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
puts("Test");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
_flushall();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
输出
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
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 属性重写函数参数的默认封送处理。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
// Marshal.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System.Runtime.InteropServices;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class PlatformInvokeTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[DllImport("msvcrt.dll")]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static extern int puts([MarshalAs(UnmanagedType.LPStr)] string m);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[DllImport("msvcrt.dll")]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
internal static extern int _flushall();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static void Main()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
puts("Hello World!");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
_flushall();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
输出
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
运行此示例时,字符串
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
Hello World!
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
将显示在控制台上。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
代码讨论
在前面的示例中,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 属性描述前面的结构,如下所示:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
// logfont.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
// compile with: /target:module
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System.Runtime.InteropServices;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
[StructLayout(LayoutKind.Sequential)]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
public class LOGFONT
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public const int LF_FACESIZE = 32;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public int lfHeight;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public int lfWidth;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public int lfEscapement;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public int lfOrientation;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public int lfWeight;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfItalic;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfUnderline;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfStrikeOut;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfCharSet;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfOutPrecision;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfClipPrecision;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfQuality;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public byte lfPitchAndFamily;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=LF_FACESIZE)]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public string lfFaceName;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
有关 StructLayout 属性的语法的更多信息,请参见 StructLayoutAttribute 类。
然后即可将该结构用在 C# 代码中,如下所示:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
// pinvoke.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
// compile with: /addmodule:logfont.netmodule
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System.Runtime.InteropServices;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class PlatformInvokeTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[DllImport("gdi32.dll", CharSet=CharSet.Auto)]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static extern IntPtr CreateFontIndirect(
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[In, MarshalAs(UnmanagedType.LPStruct)]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
LOGFONT lplf // characteristics
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
[DllImport("gdi32.dll")]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static extern bool DeleteObject(
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
IntPtr handle
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static void Main()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
LOGFONT lf = new LOGFONT();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
lf.lfHeight = 9;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
lf.lfFaceName = "Arial";
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
IntPtr handle = CreateFontIndirect(lf);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
if (IntPtr.Zero == handle)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine("Can't creates a logical font.");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
else
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
if (IntPtr.Size == 4)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine("{0:X}", handle.ToInt32());
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
else
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine("{0:X}", handle.ToInt64());
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
// Delete the logical font created.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
if (!DeleteObject(handle))
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine("Can't delete the logical font");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}运行示例
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
C30A0AE5
代码讨论
在前面的示例中,
CreateFontIndirect方法使用了一个 LOGFONT 类型的参数。MarshalAs 和 In 属性用于限定此参数。程序将由此方法返回的数值显示为十六进制大写字符串。
注册回调方法
若要注册调用非托管函数的托管回调,请用相同的参数列表声明一个委托并通过 PInvoke 传递它的一个实例。在非托管端,它将显示为一个函数指针。有关 PInvoke 和回调的更多信息,请参见平台调用详解。例如,考虑以下非托管函数
MyFunction,此函数要求 callback 作为其参数之一:
typedef void (__stdcall *PFN_MYCALLBACK)();
int __stdcall MyFunction(PFN_ MYCALLBACK callback);
若要从托管代码调用
MyFunction,请声明该委托,将 DllImport 附加到函数声明,并根据需要封送任何参数或返回值:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
public delegate void MyCallback();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
[DllImport("MYDLL.DLL")]
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
public static extern void MyFunction(MyCallback callback);
同时,请确保委托实例的生存期覆盖非托管代码的生存期;否则,委托在经过垃圾回收后将不再可用。
相关文章推荐
- C# 程序员参考--平台调用教程
- C# 程序员参考--平台调用教程
- C# 程序员参考--平台调用教程
- C# 程序员参考--属性教程
- C#.DLL Import 平台调用PInvoke教程
- C# 程序员参考--属性教程
- C# 程序员参考--数组教程
- C# 程序员参考--线程处理教程
- C# 程序员参考-委托教程(From MSDN)
- C# 程序员参考--COM Interop 第一部分:C# 客户端教程
- C#入门教程(一)–.Net平台技术介绍、C#语言及开发工具介绍-打造C#学习教程
- C# 数字证书微信API调用使用参考事例
- 【ASP.NET Web API教程】3.3 通过WPF应用程序调用Web API(C#)
- 国内首本全面深入介绍.NET互操作技术(P/Invoke『或PInvoke,平台调用』,C++ Interop『C++/CLI』,COM Interop)的参考书籍
- C#程序员的春天之从零开始学习unity3D游戏开发入门教程一(前言)
- 短信平台接口调用教程
- 国内第一部C#.Net调用Matlab混合编程视频教程
- C#调用C++ 平台调用P/Invoke 结构体--输入输出参数、返回值、返出值、结构体数组作为参数【五】
- 0基础学C#教程2--------C#如何调用excel,试用最新版的excel
- [科普小短文]在C#中调用C语言函数(静态调用Native DLL,Windows & Microsoft.Net平台)