c# intPtr 转换为 string 的问题

lihui_life 2015-12-19 09:51:21
c++函数原型
 /// <summary>
/// 读卡
/// </summary>
///参数:int ReadCard(char *room, char *gate,char *stime, char *guestname, char *guestid, char *track1, char *track2, long *cardno, int *st, int *Breakfast);
///room [out]:字符串指针,接收返回的房号,建议10字节。
///gate [out]:字符串指针,接收返回的授权公共通道,可以为NULL。
///Guestname [out]:字符串指针,接收返回的客人姓名,可以为NULL。
///Guestid [out]:字符串指针,接收返回的客人ID,可以为NULL。
///track1 [out]:接收磁卡第1轨数据,可以为NULL。
///track2 [out]:接收磁卡第2轨数据,可以为NULL。
///Cardno [out]:长整形指针,接收返回的卡号,可以为NULL。
///St [out]:整形指针,接收返回的卡状态,1-正常使用,3-正常注销,4-遗失注销,5-损毁注销,6-自动注销。可以为NULL。
///Breakfast [in]: 整形指针,接收早餐券数量。可以为NULL。

//[DllImport("MainDll.dll", CharSet = CharSet.Ansi)]
// public static extern int ReadCard(ref string room, ref string gate, ref string stime, ref string guestname, ref string guestid, ref string track1, ref string track2, ref int cardno, ref int st);

[DllImport("MainDll.dll", CharSet = CharSet.Ansi)]
public static extern int ReadCard(ref IntPtr room, ref IntPtr gate, ref IntPtr stime, ref IntPtr guestname, ref IntPtr guestid, ref IntPtr track1, ref IntPtr track2, ref IntPtr cardno, ref IntPtr st);


调用
  IntPtr room = IntPtr.Zero;
IntPtr gate = IntPtr.Zero;
IntPtr stime = IntPtr.Zero;

IntPtr guestName = IntPtr.Zero;
IntPtr guesiID = IntPtr.Zero;
IntPtr track1 = IntPtr.Zero;
IntPtr track2 = IntPtr.Zero;
IntPtr cardNo = IntPtr.Zero;
IntPtr st = IntPtr.Zero;

int num = BLL.BLLADELCard.Init("");

int result = BLL.BLLADELCard.ReadCard(ref room, ref gate, ref stime, ref guestName, ref guesiID, ref track1, ref track2, ref cardNo, ref st);
string strRoom = Marshal.PtrToStringAnsi(room);


这样读取成功,room 拿到的数据时 825242161,
转换 string string strRoom = Marshal.PtrToStringAnsi(room); strRoom 的值为“”
求~~~ 什么问题呢?
...全文
1190 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
jyf19 2019-06-24
  • 打赏
  • 举报
回复
图片发错了
yangdeshun888 2017-05-17
  • 打赏
  • 举报
回复
引用 楼主 lihuioooo 的回复:
c++函数原型
 /// <summary>
        /// 读卡
        /// </summary>
        ///参数:int ReadCard(char *room, char *gate,char *stime, char *guestname, char *guestid, char *track1, char *track2, long *cardno, int *st, int *Breakfast);
        ///room [out]:字符串指针,接收返回的房号,建议10字节。
        ///gate [out]:字符串指针,接收返回的授权公共通道,可以为NULL。
        ///Guestname [out]:字符串指针,接收返回的客人姓名,可以为NULL。
        ///Guestid [out]:字符串指针,接收返回的客人ID,可以为NULL。
        ///track1 [out]:接收磁卡第1轨数据,可以为NULL。
        ///track2 [out]:接收磁卡第2轨数据,可以为NULL。
        ///Cardno [out]:长整形指针,接收返回的卡号,可以为NULL。
        ///St [out]:整形指针,接收返回的卡状态,1-正常使用,3-正常注销,4-遗失注销,5-损毁注销,6-自动注销。可以为NULL。
        ///Breakfast [in]: 整形指针,接收早餐券数量。可以为NULL。

        //[DllImport("MainDll.dll", CharSet = CharSet.Ansi)]
       // public static extern int ReadCard(ref string room, ref  string gate, ref string stime, ref string guestname, ref string guestid, ref  string track1, ref  string track2, ref  int cardno, ref  int st);

        [DllImport("MainDll.dll", CharSet = CharSet.Ansi)]
        public static extern int ReadCard(ref IntPtr room, ref  IntPtr gate, ref IntPtr stime, ref IntPtr guestname, ref IntPtr guestid, ref  IntPtr track1, ref  IntPtr track2, ref  IntPtr cardno, ref  IntPtr st);
调用
  IntPtr room = IntPtr.Zero;
            IntPtr gate = IntPtr.Zero;
            IntPtr stime = IntPtr.Zero;

            IntPtr guestName = IntPtr.Zero;
            IntPtr guesiID = IntPtr.Zero;
            IntPtr track1 = IntPtr.Zero;
            IntPtr track2 = IntPtr.Zero;
            IntPtr cardNo = IntPtr.Zero;
            IntPtr st = IntPtr.Zero;

            int num = BLL.BLLADELCard.Init("");

            int result = BLL.BLLADELCard.ReadCard(ref room, ref gate, ref stime, ref guestName, ref guesiID, ref track1, ref track2, ref cardNo, ref st);
            string strRoom = Marshal.PtrToStringAnsi(room);
这样读取成功,room 拿到的数据时 825242161, 转换 string string strRoom = Marshal.PtrToStringAnsi(room); strRoom 的值为“” 求~~~ 什么问题呢?
解决方法:这个 string strRoom = Marshal.PtrToStringAnsi(room);是可以转化为string的,如果你的为空,则说明dll传回来的字符串是空的,这个原因肯定是因为你返回的字符串是局部char*变量,你应当在char前加个static变量, 例如:static char* name;这样就不会返回空了。
  • 打赏
  • 举报
回复
825242161这个是指针指向的地址吧,不是什么room 如果是const char* 可以用string,函数内是不会再改变的 char*你要自己分配空间,一般用StringBuiler或者byte[],试试 ReadCard([MarshalAs(UnmanagedType.LPStr)] StringBuilder room, 其他类似 一般是不需要加ref的,除非函数内会对room重新赋值(并且要求调用者自己释放),而不是改变room引用的字符串 如果是COM组件,优先尝试用[MarshalAs(UnmanagedType.BStr)]
zym8210 2015-12-21
  • 打赏
  • 举报
回复
还有就是,你这个库是成熟的库吗。如果库里面,直接把指针,指向了一个局部变量,那肯定会空了
zym8210 2015-12-21
  • 打赏
  • 举报
回复
intptr类型就不用 ref了。
xian_wwq 2015-12-21
  • 打赏
  • 举报
回复
使用stringbuilder来对应char* 按照char数组的长度,初始化stringbuilder 原则上来讲api是谁使用,就是谁申请空间
白衣如花 2015-12-21
  • 打赏
  • 举报
回复
试试不要ref,直接intPtr
lihui_life 2015-12-21
  • 打赏
  • 举报
回复
引用 12 楼 dongxinxi 的回复:
825242161这个是指针指向的地址吧,不是什么room 如果是const char* 可以用string,函数内是不会再改变的 char*你要自己分配空间,一般用StringBuiler或者byte[],试试 ReadCard([MarshalAs(UnmanagedType.LPStr)] StringBuilder room, 其他类似 一般是不需要加ref的,除非函数内会对room重新赋值(并且要求调用者自己释放),而不是改变room引用的字符串 如果是COM组件,优先尝试用[MarshalAs(UnmanagedType.BStr)]
感谢 dongxinxi 用[MarshalAs(UnmanagedType.LPStr)] StringBuilder room 接收数据成功, 问题解决了, 直接用StringBuilder 是不行的,需要加[MarshalAs(UnmanagedType.LPStr)] 修饰 谢谢各位啦
crystal_lz 2015-12-20
  • 打赏
  • 举报
回复
把你所有的 ref IntPtr 换成 StringBuilder
孤独de猫 2015-12-20
  • 打赏
  • 举报
回复
把字符串接收的类型,改成StringBuilder,或string类型。
lihui_life 2015-12-19
  • 打赏
  • 举报
回复
引用 4 楼 sunny906 的回复:
不行,就用auto看看

[DllImport("MainDll.dll", CharSet = CharSet.Auto)]
Marshal.PtrToStringAuto
测试了 CharSet.Auto 和CharSet.Unicode 直接就报错了。 “System.AccessViolationException”类型的未经处理的异常在 mscorlib.dll 中发生 其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
sunny906 2015-12-19
  • 打赏
  • 举报
回复
写错了,应该是这样

[DllImport("MainDll.dll", CharSet = CharSet.Unicode)]
string    string strRoom = Marshal.PtrToStringUni(room);
sunny906 2015-12-19
  • 打赏
  • 举报
回复
不行,就用auto看看

[DllImport("MainDll.dll", CharSet = CharSet.Auto)]
Marshal.PtrToStringAuto
sunny906 2015-12-19
  • 打赏
  • 举报
回复
可能是编码问题,改成unicode看看

[DllImport("MainDll.dll", CharSet = CharSet.Unicode)]
string    string strRoom = Marshal.PtrToStringAnsi(room); 
lihui_life 2015-12-19
  • 打赏
  • 举报
回复
周六都休息了
赋所有源代码,开发工具vs2010 framework3.5 baidu搜索c# HidUsb都是大同小异案例,而且拿下来基本不能用。大都是围绕public static extern int CreateFile(省略众多参数..);发现没有,copy下来测试基本都是用不了的。 原因很简单:windows不允许你用程序随便就去访问硬件设备。所以在此把之前做过的基于C#开发读写HidUsb设备的项目整理成一个简单的小案例,分享给大家,开发环境VS2010。 该案例重点在public static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile); 看着貌似也是用到CreateFile这个函数,其实并不然,注意到没有"SafeFileHandle",这就是重点! 这样windows是允许程序访问外接hidusb设备的。 当然具体如何运用这个函数现在已经不是您应该 关心的了,因为我已经为您把它封装成一个类,您只要调用相应的方法就OK. 例: //第一步:获取HidUsb设备信息 List slist = new List(); UsbHidDevice usbhid = new UsbHidDevice(); usbhid.GetDeviceList(ref slist); //HidUsb设备信息包含在List数据集中 注:当获取到HidUsb设备信息为:\\?\hid#vid_0e2c&pid;_0112#6&1b44c403;&0&0000;#{4d1e55b2-f16f-11cf-88cb-001111000030}, 注意该字符串里的“vid_0e2c”和“pid_0112”部分,那么: vid为0e2c, pid为:0112 //第二步:创建一个HidUsb设备访问实例 UsbHidDevice Device = new UsbHidDevice(vid, pid); //第三步:连接HidUsb设备 Boolean connBool = Device.Connect(); //第四步:实现数据接收事件 Device.DataReceived += new UsbHidDevice.DataReceivedDelegate(Device_DataReceived); //当HidUsb设备返回信息时触发此事件 void Device_DataReceived(byte[] data) { //处理接收到的数据逻辑 } //第五步:向Hid设备发送数据"0xa0 00 0x12 0x9 0x22" string txt = "0xa0 00 0x12 0x9 0x22"; //把数据转换为字节数组 byte[] data = ConvertHelper.StringToByte(txt2); byte bt = 0; CommandMessage cmdMsg = new CommandMessage(bt, data); Boolean sbool = Device.SendMessage(cmdMsg); //发送数据 //第六步:释放所有资源 Device.Dispose();
baidu搜索c# HidUsb都是大同小异案例,而且拿下来基本不能用。大都是围绕public static extern int CreateFile(省略众多参数..);发现没有,copy下来测试基本都是用不了的。 原因很简单:windows不允许你用程序随便就去访问硬件设备。所以在此把之前做过的基于C#开发读写HidUsb设备的项目整理成一个简单的小案例,分享给大家,开发环境VS2010。 该案例重点在public static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile); 看着貌似也是用到CreateFile这个函数,其实并不然,注意到没有"SafeFileHandle",这就是重点! 这样windows是允许程序访问外接hidusb设备的。 当然具体如何运用这个函数现在已经不是您应该关心的了,因为我已经为您把它封装成一个类,您只要调用相应的方法就OK. 例:当获取到HidUsb设备信息为:\\?\hid#vid_0e2c&pid_0112#6&1b44c403&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} 那么: vid为0e2c, pid为:0112 //创建一个HidUsb设备访问实例 UsbHidDevice Device = new UsbHidDevice(vid, pid); //实现数据接收事件 Device.DataReceived += new UsbHidDevice.DataReceivedDelegate(Device_DataReceived); //当HidUsb设备返回信息时触发此事件 void Device_DataReceived(byte[] data){ } //向Hid设备发送数据"0xa0 00 0x12 0x9 0x22" string txt = "0xa0 00 0x12 0x9 0x22"; //把数据转换为字节数组 byte[] data = ConvertHelper.StringToByte(txt2); byte bt = 5; CommandMessage cmdMsg = new CommandMessage(bt, data); Boolean sbool = Device.SendMessage(cmdMsg); //发送数据 Device.Dispose(); //释放所有资源
baidu搜索c# HidUsb都是大同小异案例,而且拿下来基本不能用。大都是围绕public static extern int CreateFile(省略众多参数..);发现没有,copy下来测试基本都是用不了的。 原因很简单:windows不允许你用程序随便就去访问硬件设备。所以在此把之前做过的基于C#开发读写HidUsb设备的项目整理成一个简单的小案例,分享给大家,开发环境VS2010。 该案例重点在public static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile); 看着貌似也是用到CreateFile这个函数,其实并不然,注意到没有"SafeFileHandle",这就是重点! 这样windows是允许程序访问外接hidusb设备的。 当然具体如何运用这个函数现在已经不是您应该关心的了,因为我已经为您把它封装成一个类,您只要调用相应的方法就OK. 例: 获取HidUsb设备信息 List slist = new List(); UsbHidDevice usbhid = new UsbHidDevice(); usbhid.GetDeviceList(ref slist); //HidUsb设备信息包含在List数据集中 当获取到HidUsb设备信息为:\\?\hid#vid_0e2c&pid_0112#6&1b44c403&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} 那么: vid为0e2c, pid为:0112 //创建一个HidUsb设备访问实例 UsbHidDevice Device = new UsbHidDevice(vid, pid); //实现数据接收事件 Device.DataReceived += new UsbHidDevice.DataReceivedDelegate(Device_DataReceived); //当HidUsb设备返回信息时触发此事件 void Device_DataReceived(byte[] data){ } //向Hid设备发送数据"0xa0 00 0x12 0x9 0x22" string txt = "0xa0 00 0x12 0x9 0x22"; //把数据转换为字节数组 byte[] data = ConvertHelper.StringToByte(txt2); byte bt = 0; CommandMessage cmdMsg = new CommandMessage(bt, data); Boolean sbool = Device.SendMessage(cmdMsg); //发送数据 Device.Dispose(); //释放所有资源

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧