




已阅读5页,还剩5页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C#调C+的dll的函数C+struct HHFC_SETchar* UID;int code;extern C _declspec(dllexport) int PReadUID(HHFC_SET* mystruct, char* lpKeyNo, LPTSTR lpKeyNo2 )/int a=5;CString ds=sea中国;/wchar_t a = Lsea;/lpKeyNo = (LPTSTR)(LPCTSTR)a;/lpKeyNo = L中国a;strcpy(lpKeyNo,中国aabbbcccc);wcscpy(lpKeyNo2,L中国aabbbcccc);/lpKeyNo0 = La;/lpKeyNo1 = Lb;/lpKeyNo2 = Lc;/lpKeyNo3 = L0;/:MessageBox(NULL, lpKeyNo, Linfo, MB_OK);/ mystruct-UID=ds.GetBuffer(ds.GetLength()+1);mystruct-UID=seaaa中国;return 5;C#using System;using System.Runtime.InteropServices;using System.Text;namespace PInvoke/ / Ivoke 的摘要说明。/ /public class IvokeDllImport(standerMFC.dll, EntryPoint = PReadUID, CharSet = CharSet.Ansi)/nPort:1代表COM1,返回-1代表已经打开COM PORT失败,0代表COM已经打开,返回其它值表示打开对应的COMpublic static extern int PReadUID(ref HHFC_SET stru,MarshalAs(UnmanagedType.LPStr) StringBuilder sb,MarshalAs(UnmanagedType.LPWStr) StringBuilder sb2);StructLayout(LayoutKind.Sequential)public struct HHFC_SETMarshalAs(UnmanagedType.LPStr)public String Uid;MarshalAs(UnmanagedType.I4)public int code;namespace PInvoke/ / Class1 的摘要说明。/ class Class1/ / 应用程序的主入口点。/ STAThreadstatic void Main(string args)/ TODO: 在此处添加代码以启动应用程序/HHFC_SET stru=new HHFC_SET ();stru.Uid=;Console.WriteLine(stru.Uid);StringBuilder sb = new StringBuilder(80);StringBuilder sb2 = new StringBuilder(80);int a = Ivoke.PReadUID(ref stru, sb, sb2);/Ivoke.GetUsbkeyNo();Console.WriteLine(stru.Uid);Console.Read();注意:char* 用UnmanagedType.LPStrwchar_t* 用UnmanagedType.LPWStrC#中调用非托管的DLL及参数传递本篇文章来源于:开发学院 原文链接:/2010/0531/23111.php微软的.NET框架的优点之一是它提供了独立于语言的开发平台。你可以在VB、C+、C#等语言中编写一些类,而在其它语言中使用(源于.NET中使用了CLS),你甚至可以从另一种语言编写的类中继承。但是你要是想调用以前的非托管DLL,微软的.NET框架的优点之一是它提供了独立于语言的开发平台。你可以在VB、C+、C#等语言中编写一些类,而在其它语言中使用(源于.NET中使用了CLS),你甚至可以从另一种语言编写的类中继承。但是你要是想调用以前的非托管DLL,那又会怎么样呢?你必须以某种方式将.NET对象转换为结构体、char *、函数指针等类型。这也就是说,你的参数必须被marshal(注:不知道中文名称该叫什么,英文中指的是为了某个目的而组织人或事物,参见这里,此处指的是为了调用非托管函数而进行的参数转换)。C#中使用DLL函数之前,你必须使用DllImport声明要调用的函数:public class Win32 DllImport(User32.Dll)public static extern void SetWindowText(int h, String s);/ 函数原型为:BOOL SetWindowText(HWND hWnd, LPCTSTR lpString); DllImport告诉编译器被调函数的入口在哪里,并且将该入口绑定到类中你声明的函数。你可以给这个类起任意的名字,我给它命名为Win32。你甚至可以将类放到命名空间中,具体参见图一。要编译Win32API.cs,输入:csc /t:library /out:Win32API.dll Win32API.cs 这样你就拥有了Win32API.dll,并且你可以在任意的C#项目中使用它:using Win32API;int hwnd = / get it.String s = Im so cute.Win32.SetWindowText(hwnd, s); 编译器知道去user32.dll中查找函数SetWindowText,并且在调用前自动将String转换为LPTSTR (TCHAR*)。很惊奇是吧!那么.NET是如何做到的呢?每种C#类型有一个默认的marshal类型,String对应LPTSTR。但你若是试着调用GetWindowText会怎么样呢(此处字符串作为out参数,而不是in参数)?它无法正常调用,是因为String是无法修改的,你必须使用StringBuilder:using System.Text; / for StringBuilderpublic class Win32 DllImport(user32.dll)public static extern int GetWindowText(int hwnd,StringBuilder buf, int nMaxCount);/ 函数原型:int GetWindowText(HWND hWnd, LPTSTR lpString, int nMaxCount); StringBuilder默认的marshal类型是LPTSTR,此时GetWindowText可以修改你的字符串:int hwnd = / get it.StringBuilder cb = new StringBuilder(256);Win32.GetWindowText(hwnd, sb, sb.Capacity); 如果默认的类型转换无法满足你的要求,比如调用函数GetClassName,它总是将参数转换为类型LPSTR (char *),即便在定义Unicode的情况下使用,CLR仍然会将你传递的参数转换为TCHAR类型。不过不用着急,你可以使用MarshalAs覆盖掉默认的类型:DllImport(user32.dll)public static extern int GetClassName(int hwnd,MarshalAs(UnmanagedType.LPStr) StringBuilder buf,int nMaxCount);/ 函数原型:int GetClassNameA(HWND hWnd, LPTSTR lpClassName, int nMaxCount); 这样当你调用GetClassName时,.NET将字符串作为ANSI字符传递,而不是宽字符。结构体和回调函数类型的参数又是如何传递的呢?.NET有一种方法可以处理它们。举个简单的例子,GetWindowRect,这个函数获取窗口的屏幕坐标,C+中我们这么处理:/ in C/C+RECT rc;HWND hwnd = FindWindow(foo,NULL);:GetWindowRect(hwnd, &rc); 你可以使用C#结构体,只需使用另外一种C#属性StructLayout:StructLayout(LayoutKind.Sequential)public struct RECT public int left;public int top;public int right;public int bottom; 一旦你定义了上面的结构体,你可以使用下面的函数声明形式 :DllImport(user32.dll)public static extern intGetWindowRect(int hwnd, ref RECT rc);/ 函数原型:BOOL GetWindowRect(HWND hWnd, LPRECT lpRect);使用ref标识很重要,以至于CLR(通用语言运行时)将RECT变量作为引用传递到函数中,而不是无意义的栈拷贝。定义了GetWindowRect之后,你就可以采用下面的方式调用:RECT rc = new RECT();int hwnd = / get it .Win32.GetWindowRect(hwnd, ref rc); 注意你同样需要像声明中的那样使用ref关键字。C#结构体默认的marshal类型是LPStruct,因此没有必要使用MarshalAs。但如果你使用了类RECT而不是结构体RECT,那么你必须使用如下的声明形式:/ if RECT is a class, not structDllImport(user32.dll)public static extern intGetWindowRect(int hwnd,MarshalAs(UnmanagedType.LPStruct) RECT rc); C#和C+一样,一件事情有很多中实现方式。System.Drawing中已经有Rectangle结构体,用来处理矩形,那有为什么要“重新发明轮子”呢?DllImport(user32.dll)public static extern int GetWindowRect(int hwnd, ref Rectangle rc); 最后,又是怎样从C#中传递回调函数到非托管代码中的呢?你所要做的就是委托(delegate)。delegate bool EnumWindowsCB(int hwnd, int lparam); 一旦你声明了你的回调函数,那么你需要调用的函数声明为:DllImport(user32)public static extern intEnumWindows(EnumWindowsCB cb, int lparam);/ 函数原型:BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);由于上面的委托仅仅是声明了委托类型,你需要在你的类中提供实际的回调函数代码。/ in your classpublic static bool MyEWP(int hwnd, int lparam) / do somethingreturn true; 然后传递给相应的委托变量:EnumWindowsCB cb = new EnumWindowsCB(MyEWP);Win32.EnumWindows(cb, 0); 你可能注意到参数lparam。在C语言中,如果你传递参数LPARAM给EnumWindows,Windows将它作为参数调用你的回调函数。通常lparam是包含了你要做的事情的上下文结构体或类指针,记住,在.NET中没有指针的概念!那该怎么做呢?上面的例子中,你可以申明lparam为IntPtr类型,并且使用GCHandle来封装它:/ lparam is IntPtr nowdelegate bool EnumWindowsCB(int hwnd, IntPtr lparam);/ wrap object in GCHandleMyClass obj = new MyClass();GCHandle gch = GCHandle.Alloc(obj);EnumWindowsCB cb = new EnumWindowsCB(MyEWP);Win32.EnumWindows(cb, (IntPtr)gch);gch.Free(); 不要忘了使用完之后手动释放它!有时,你需要按照以前那种方式在C#中释放内存。可以使用GCHandle.Target的方式在你的回调函数中使用“指针”。public static bool MyEWP(int hwnd, IntPtr param) GCHandle gch = (GCHandle)param;MyClass c = (MyClass)gch.Target;/ . use itreturn true; 图2是将EnumWindows封装到数组中的类。你只需要按如下的方式使用即可,而不要纠结于委托和回调中。WindowArray wins = new WindowArray();foreach (int hwnd in wins) / do something 关于委托代码和非委托代码之间交互的更多内容,你可以参考.NET文档中的“平台调用教程”。C#调用dll时的类型转换总结C+(Win 32)C#char*作为输入参数转为char,通过Encoding类对这个string进行编码后得到的一个char作为输出参数转为byte,通过Encoding类对这个byte进行解码,得到字符串C+ Dll接口:void CplusplusToCsharp(in char* AgentID, out char* AgentIP);C#中的声明:DllImport(Example.dll)public static extern void CplusplusToCsharp(char AgentID, byte AgentIP);C#中的调用:Encoding encode = Encoding.Default;byte tAgentID;byte tAgentIP;string AgentIP;tAgentID = new byte100;tAgentIP = new byte100;CplusplusToCsharp(encode.GetChars(tAgentID), tAgentIP);AgentIPi = encode.GetString(tAgentIP,i*Length,Length);HandleIntPtrHwndIntPtrint*ref intint&ref intvoid*IntPtrunsigned char*ref byteBOOLboolDWORDint或uint(int更常用一些)枚举类型Win32:BOOL MessageBeep(UINT uType /声音类型);其中的声音类型为枚举类型中的某一值。C#:用户需要自己定义一个枚举类型:public enum BeepTypeSimpleBeep = -1,IconAsterisk = 0x00000040,IconExclamation = 0x00000030,IconHand = 0x00000010,IconQuestion = 0x00000020,Ok = 0x00000000,C#中导入该函数:DllImport(user32.dll)public static extern bool MessageBeep(BeepType beepType);C#中调用该函数:MessageBeep(BeepType.IconQuestion);结构类型Win32:使用结构指针作为参数的函数:BOOL GetSystemPowerStatus(LPSYSTEM_POWER_STATUS lpSystemPowerStatus);Win32中该结构体的定义:typedef struct _SYSTEM_POWER_STATUS BYTEACLineStatus;BYTEBatteryFlag;BYTEBatteryLifePercent;BYTEReserved1;DWORDBatteryLifeTime;DWORDBatteryFullLifeTime; SYSTEM_POWER_STATUS, *LPSYSTEM_POWER_STATUS;C#:用户自定义相应的结构体:struct SystemPowerStatusbyte ACLineStatus;byte batteryFlag;byte batteryLifePercent;byte reserved1;int batteryLifeTime;int batteryFullLifeTime;C#中导入该函数:DllImport(kernel32.dll)public static extern bool GetSystemPowerStatus(ref SystemPowerStatus systemPowerStatus);C#中调用该函数:SystemPowerStatus sps;.sps初始化赋值GetSystemPowerStatus(ref sps);字符串对于字符串的处理分为以下几种情况:1、字符串常量指针的处理(LPCTSTR),也适应于字符串常量的处理,.net中的string类型是不可变的类型。2、字符串缓冲区的处理(char*),即对于变长字符串的处理,.net中StringBuilder可用作缓冲区Win32:BOOL GetFile(LPCTSTR lpRootPathName);C#:函数声明:DllImport(kernel32.dll, CharSet = CharSet.Auto)static extern bool GetFile (MarshalAs(UnmanagedType.LPTStr)string rootPathName);函数调用:string pathname;GetFile(pathname);备注:DllImport中的CharSet是为了说明自动地调用该函数相关的Ansi版本或者Unicode版本变长字符串处理:C#:函数声明:DllImport(kernel32.dll, CharSet = CharSet.Auto)public static extern int GetShortPathName(MarshalAs(UnmanagedType.LPTStr)string path,MarshalAs(UnmanagedType.LPTStr)StringBuilder shortPath,int shortPathLength);函数调用:StringBuilder shortPath = new StringBuilder(80);int result = GetShortPathName(d:test.jpg, shortPath, shortPath.Capacity);string s = shortPath.ToString();struct具有内嵌字符数组的结构:Win32:typedef struct _TIME_ZONE_INFORMATION LONGBias;WCHARStandardName 32 ;SYSTEMTIME StandardDate;LONGStandardBias;WCHARDaylightName 32 ;SYSTEMTIME DaylightDate;LONGDaylightBias; TIME_ZONE_INFORMATI
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 公路桥梁建设与加固技术方案
- 年产5000吨速冻食品、卤制食品项目可行性研究报告模板-立项备案
- 初中物理电学试题及答案
- 2025沧州期末考试真题及答案
- 2025年高处维护安全作业试题及答案
- 直播平台集成与支持方案
- 土石方工程环境保护措施方案
- 建筑排水管网防渗方案
- 2025博州教师编制考试真题及答案
- 林业公司笔试题型及答案
- 《资治通鉴》与为将之道知到课后答案智慧树章节测试答案2025年春武警指挥学院
- 2025年无线电装接工(中级)职业技能考试题(附答案)
- 2024年秋季新北师大版七年级上册数学全册教案设计
- 2025年地磅租赁合同协议样本
- (高清版)DB32∕T 4443-2023 罐区内在役危险化学品(常低压)储罐管理规范
- 医院培训课件:《输液泵》
- 量子通信金融应用研究报告
- DBJ51-T 184-2021 四川省预成孔植桩技术标准
- 科技创新园区租赁合同样本
- 2024建筑工程数字化交付技术标准
- 经济职业技术学院教务教学管理制度汇编(2024年)
评论
0/150
提交评论