Platform invoke 乱码
来源:互联网 发布:mac无线网经常掉线 编辑:程序博客网 时间:2024/06/04 19:54
最近在做一个关于智能卡的项目的时候,遇到一个乱码的问题,具体情况是这样的,调用API的一个方法的时候,在传递的一个结构体变量中有字符串类型的变量,该变量从API中返回的时候变成了乱码,而和它同一个结构体的整型值却是个正常的值。
typedef struct {
LPSTR ErrorNumber; /* Error Number */
LPSTR ErrorString; /* Description of the error */
LPSTR ResolutionString; /* Description of the resolution for the error. */
DWORD HelpID; /* help identifier for the error */
} CARD_ERROR_INFO_1_A, *PCARD_ERROR_INFO_1_A, FAR *LPCARD_ERROR_INFO_1_A;
#ifndef HOST_16BIT
typedef struct {
LPWSTR ErrorNumber; /* Error Number */
LPWSTR ErrorString; /* Description of the error */
LPWSTR ResolutionString; /* Description of the resolution for the error. */
DWORD HelpID; /* help identifier for the error */
} CARD_ERROR_INFO_1_W, *PCARD_ERROR_INFO_1_W, FAR *LPCARD_ERROR_INFO_1_W;
#endif
#if defined _UNICODE || defined UNICODE
#define LPCARD_ERROR_INFO_1 LPCARD_ERROR_INFO_1_W
#else
#define LPCARD_ERROR_INFO_1 LPCARD_ERROR_INFO_1_A
BOOL ICEAPI GetCardPrinterErrors (LPTSTR lpPrinterName,DWORD level,LPCARD_ERROR_INFO_1 lpbErrorInfo, DWORD cbBuf, LPDWORD lpdwNeeded,LPDWORD lpdwError);
下面是对应的C#的方法,在转化前,先要搞清楚几个数据类型,从WinNT.h 中可以看到
LPSTR 实际上就是 char* ,LPWSTR = WCHAR*, WCHAR是Unicode 类型的字符(用2Bytes分配一个字符),而ANSI则用一个Byte来分配字符。char就是Ansi类型。
为了实验方便,我把上面的方法的参数变成一个,LPCARD_ERROR_INFO_1 lpbErrorInfo
还有C#部分的关于MarshalAs 和structlayout 的知识
1.基础部分
MarshalAs是什么?它可以用来做什么?
MarshalAs 这个属性用来指示如何在托管代码和非托管代码之间封送数据,可以用于参数,字段或者返回值.该属性为可选属性,因为每个数据类型都有默认的封送处理行为.仅在可以将给定类型封送到多个类型时需要此属性.(MSDN).从这里看,并不是每个p/invoke 或者 com invoke都要用到MarshalAS的.
StructLayoutAttribute 类使用户可以控制类或结构的数据字段的物理布局.
通常,公共语言运行库控制类或结构的数据字段在托管内存中的物理布局。如果类或结构需要按某种方式排列,则可以使用 StructLayoutAttribute。如果要将类传递给需要指定布局的非托管代码,则显式控制类布局是重要的。LayoutKind 值 Sequential 用于强制将成员按其出现的顺序进行顺序布局。Explicit 控制每个数据成员的精确位置。如果使用 Explicit,则每个成员必须使用 FieldOffsetAttribute 来指示该字段在类型中的位置.(MSDN)
[StructLayout(LayoutKind.Sequential)]
public struct testAttr
{
[MarshalAs(UnmanagedType.LPTStr)]
public string ErrorNumber;
[MarshalAs(UnmanagedType.LPTStr)]
public string ErrorString;
[MarshalAs(UnmanagedType.LPTStr)]
public string ResolutionString;
public UInt32 HelpID;
}
[DllImport("PlatformCPlusPlus.dll", EntryPoint = "GetCardPrinterErrors")]
extern static int GetCardPrinterErrors(ref testAttr ta);
一开始这样做的时候是出现乱码的,后来仔细看下,原来 LPTSTR在winnt ,winxp中的系统中都是Unicode编码,所以会出现乱码,默认的是用Ansi的,最后的解决方法是,将 [MarshalAs(UnmanagedType.LPTStr)]去掉就可以了
下面是实验用的代码
#ifdef PLATFORMCPLUSPLUS_EXPORTS
#define ICEAPI __declspec(dllexport)
#else
#define ICEAPI __declspec(dllimport)
#endif
ICEAPI BOOL GetCardPrinterErrors1A(LPCARD_ERROR_INFO_1); } ICEAPI BOOL GetCardPrinterErrors1A }
extern "C"
{
typedef struct
{
LPSTR ErrorNumber;
LPSTR ErrorString;
LPSTR ResolutionString;
DWORD HelpID;
}*LPCARD_ERROR_INFO_1;
(
LPCARD_ERROR_INFO_1 lpCard
)
{
char* temp = (char*)CoTaskMemAlloc(sizeof(char) * strlen(lpCard->ErrorString) + 6);
strcpy_s(temp,sizeof(char) * (strlen(lpCard->ErrorString) + 6),"test:");
lpCard->ErrorString = temp;
lpCard->ErrorNumber = temp;
lpCard->ResolutionString = temp;
lpCard->HelpID = 123456;
return true;
[DllImport("PlatformCPlusPlus.dll", EntryPoint = "GetCardPrinterErrors1A", CharSet = CharSet.Ansi)]
extern static int GetCardPrinterErrors(ref testAttr ta);
static void Main(string[] args)
{
testAttr taa = new testAttr();
taa.ErrorNumber = string.Empty;
taa.ErrorString = string.Empty;
taa.HelpID = 0;
taa.ResolutionString = string.Empty;
GetCardPrinterErrors(ref taa);
Console.WriteLine(taa.ErrorNumber);
Console.WriteLine(taa.ErrorString);
Console.WriteLine(taa.ResolutionString);
Console.WriteLine(taa.HelpID.ToString());
Console.Read();
}
所以,以后做类似的平台调用涉及到string的都必须要指定该string用的是什么样的编码格式,否则,会出现乱码的情况
而且要明白一点,所提高api的平台,支持的是什么编码格式。
- Platform invoke 乱码
- PlatForm Invoke Technology Sample
- Platform Invoke Tutorial
- c#.NET Framework 关机代码 Platform Invoke
- C#调用C++代码(CSharp Platform Invoke)
- Invoke
- Invoke
- invoke
- Invoke
- Invoke()
- Linux Platform Java应用程序汉字乱码解决办法
- Delphi2005学习笔记2——Using Platform Invoke with Delphi 2005
- platform
- platform
- platform
- platform
- platform
- platform
- DirectShow翻译
- 如何对ArcSDE空间网格大小进行优化?
- mysql 链接查询
- [转载]大型高并发高负载网站的系统架构
- 搜索引擎技术内幕之索引
- Platform invoke 乱码
- DirectShow之事件通知机制(转)
- oracle语句随写
- MYSQL操作语法(整理一)
- 简单的“TCP/IP筛选”
- 公开 《Unix/Linux下的Curses库开发指南》全书内容
- pb11.5 web开发 - webservice之proxy的创建
- C# ae 获取某字段唯一值
- delphi写的PING命令