.net 互操作之p/invoke- 数据封送(字符串版本-ANSI和UniCode,返回错误码,回调函数,常量)(6)...

Win32API与错误处理
本文介绍如何在.NET中调用Win32API,并详细解释了如何通过不同方法获取和处理Win32错误信息。此外,还展示了如何定义常量以匹配Win32API的功能需求。

处理字符串的函数(ANSI和UniCode版本)



非托管函数后缀名A表示ANSI,W表示宽字符(Unicode),如GetUserName有GetUserNameA和GetUserNameW

p/inlvoke设置方式

1.设置CharSet
DllImport默认为Ansi

[DllImport("advapi32.dll", CharSet = CharSet.Ansi)]

2.设置EntryPoint

[DllImport("advapi32.dll", EntryPoint = "GetUserNameA")]

3.自动行为

当设置CharSet 会自动去寻找后缀名为W和A的函数,设置ExactSpelling为true时,需要保证生命函数与非托管函数名是一致的

[DllImport("advapi32.dll", EntryPoint = "GetUserNameA", CharSet = CharSet.Auto,ExactSpelling=true)]

4.自动系统平台设置
当CharSet 设置为Auto时,会根据系统来寻找函数封送

[DllImport("advapi32.dll", EntryPoint = "GetUserNameW", CharSet = CharSet.Auto)]

错误码

首先要设置SetLastError=true

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]

两种处理方式

1.使用Win32 API FormatMessage

public class FormatErrorCode
 {
     const uint FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
     const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
     const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
 
     //Win32 API
     //DWORD WINAPI FormatMessage(
     //  __in      DWORD dwFlags,
     //  __in_opt  LPCVOID lpSource,
     //  __in      DWORD dwMessageId,
     //  __in      DWORD dwLanguageId,
     //  __out     LPTSTR lpBuffer,
     //  __in      DWORD nSize,
     //  __in_opt  va_list* Arguments
     //);
 
     [DllImport("kernel32.dll")]
     public static extern uint FormatMessage(uint dwFlags, IntPtr lpSource,
         uint dwMessageId, uint dwLanguageId, ref IntPtr lpMsgBuf,
         uint nSize, IntPtr Arguments);
 
     //Win32 API
     //HLOCAL WINAPI LocalFree(
     //  __in  HLOCAL hMem
     //);
 
     [DllImport("kernel32.dll", SetLastError = true)]
     public static extern IntPtr LocalFree(IntPtr hMem);
 
     public static string GetLastErrorMsg()
     {
         
         int lastError = Marshal.GetLastWin32Error();
 
         IntPtr lpMsgBuf = IntPtr.Zero;
 
         uint dwChars = FormatMessage(
             FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
             | FORMAT_MESSAGE_IGNORE_INSERTS,
             IntPtr.Zero, (uint)lastError, 0, ref lpMsgBuf, 0, IntPtr.Zero);
 
         if (dwChars == 0)
         {
             return "";
         }
 
         string errorMsg = Marshal.PtrToStringAnsi(lpMsgBuf);
         // 释放内存
         LocalFree(lpMsgBuf);
 
         return errorMsg;
     }
 }

测试

public static void TestErrorMsgByWin32Exception()
 {
 
         GetFileAttributes("FileNotFoundDemo.txt");
 
     // error code获得最后一次获得的错误
int lastErrorCode = Marshal.GetLastWin32Error(); // 将Win32的错误码转化成一个用户友好的托管异常 Win32Exception win32Exception = new Win32Exception(lastErrorCode); Console.WriteLine("GetFileAttributes last win32 error message: {0}", win32Exception.Message); }


2.使用托管的Win32Exception

public static void TestErrorMsgByWin32ExceptionDefault()
 {
     // 试图获得一个不存在的文件的属性
     GetFileAttributes("FileNotFoundDemo.txt");
 
     // 使用Win32的缺省构造函数,使其自动调用Marshal.GetLastWin32Error()来
     // 将Win32的错误码转化成一个用户友好的托管异常
     Win32Exception win32Exception = new Win32Exception();
     Console.WriteLine("GetFileAttributes last win32 error message: {0}", win32Exception.Message);
 }

明显的第2种简单很多,会自动去调用 Marshal.GetLastWin32Error()方法

处理回调函数

定义常量

这个比较麻烦,烦是Win32 API 定义的常量,想使用的话,必须重新定义一遍,所以找到常量的值是关键.可以讲一组功能相近的常量定义成枚举

[Flags]
 public enum FileAttributeFlags : uint
 {
     //文件属性标志
     FILE_ATTRIBUTE_READONLY = 0x00000001,
     FILE_ATTRIBUTE_HIDDEN = 0x00000002,
     FILE_ATTRIBUTE_SYSTEM = 0x00000004,
     FILE_ATTRIBUTE_DIRECTORY = 0x00000010,
     FILE_ATTRIBUTE_ARCHIVE = 0x00000020,
     FILE_ATTRIBUTE_DEVICE = 0x00000040,
     FILE_ATTRIBUTE_NORMAL = 0x00000080,
     FILE_ATTRIBUTE_TEMPORARY = 0x00000100,
     FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200,
     FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400,
     FILE_ATTRIBUTE_COMPRESSED = 0x00000800,
     FILE_ATTRIBUTE_OFFLINE = 0x00001000,
     FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000,
     FILE_ATTRIBUTE_ENCRYPTED = 0x00004000,
     FILE_ATTRIBUTE_VALID_FLAGS = 0x00007fb7,
     FILE_ATTRIBUTE_VALID_SET_FLAGS = 0x000031a7,
 }

转载于:https://www.cnblogs.com/Clingingboy/archive/2010/08/26/1809626.html

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化并行计算等改进策略。; 适合人群:具备一定Python编程基础优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值