C# 调用dll 传参数编码问题

zq1564171310 2014-11-14 06:40:57
typedef struct User
{
char user_name[30];
char user_email[40];
}User;
...全文
590 39 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
s8848 2014-11-21
  • 打赏
  • 举报
回复
中文的utf-8的定义有的是2个byte,有的是3个byte. 中文汉字数量超出了3万多个,所以需要3个byte,4个byte来描述这个汉字.不是所有的汉字都是2个byte. 之前我也碰到过这些问题,总之编码要统一起来,好处理点.
zq1564171310 2014-11-20
  • 打赏
  • 举报
回复
引用 36 楼 s8848 的回复:
没有给讲清楚,在windows的平台上.net的char是定义2个byte的.
我不是大牛,只是一个刚学C#不到4个月的渣渣,本来想找人解决问题的,但是貌似大家没有实际写这段代码,所以没有最终解决,然后只是凭借猜测,和大家宝贵的意见,拼了个解决方法出来。 至于为什么这样,我不知道,但问题解决了,所以留下代码,给后面遇见相同问题的兄弟一点帮助。当然哪位能说说其中道道,或者有更好意见,我很希望能分享一下。
zq1564171310 2014-11-20
  • 打赏
  • 举报
回复
不好意思,坑了大家一把,以为实现了,但是遇见中文个数为奇数时,还是乱码,原因unicode不可能出现i为奇数,其实还要判断i为奇数还是偶数 代码:

          if (i > 0 && (i % 2 == 0))
            {
                user_name = System.Text.Encoding.Unicode.GetString(userName, 0, i);
            }
            else
            {
                byte[] bytes = new byte[i + 1];
                for (int j = 0; j < i; j++)
                {
                    bytes[j] =userName[j];
                }
               user_name = System.Text.Encoding.Unicode.GetString(bytes, 0, i + 1);
            }
将这段添加到
引用
user_name = System.Text.Encoding.Unicode.GetString(userName, 0, i);
s8848 2014-11-20
  • 打赏
  • 举报
回复
没有给讲清楚,在windows的平台上.net的char是定义2个byte的.
zq1564171310 2014-11-19
  • 打赏
  • 举报
回复
感谢诸位大牛,虽然最终靠自己解决了,但是还是感谢诸位给的提示,最中还是弄出来了,通过UTF8的byte,然后循环到数据最后一位,break,最后转成unicode来控制编码(实际byte还是UTF8,但dll会自己将其当做UTF8解码),不一定解释对,但是可以实现 以下代码留给后面遇到同样问题的人,不一定有用,但是也是一个参考,一种思路:
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)]
    public struct User
    {
       [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
        public string user_name;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
        public string user_email;
public User(byte[ ] userName,byte[ ] userEmail)
{
            int i = 0;
            for (i = 0; i < userName.Length; i++)
            {
                if (userName[i] == 0)
                    break;
            }
             user_name = System.Text.Encoding.Unicode.GetString(userName, 0, i);

            int i = 0;
            for (i = 0; i < userEmail.Length; i++)
            {
                if (userEmail[i] == 0)
                    break;
            }
            user_email = System.Text.Encoding.Unicode.GetString(userEmail, 0, i);
    }
}
引用的时候new两个带byte数组的参数就行,而且要保证参数为UTF8
zq1564171310 2014-11-18
  • 打赏
  • 举报
回复
引用
object ICustomMarshaler.MarshalNativeToManaged(IntPtr pNativeData) { List<byte> buffer = new List<byte>(); int index = 0; while (true) { var data = Marshal.ReadByte(pNativeData, index++); if (data == 0) { break; } buffer.Add(data); } return Encoding.UTF8.GetString(buffer.ToArray()); }
请问这个如何引用?有些懵了。
Saleayas 2014-11-18
  • 打赏
  • 举报
回复
		object ICustomMarshaler.MarshalNativeToManaged(IntPtr pNativeData)
		{
			List<byte> buffer = new List<byte>();
			int index = 0;
			while (true)
			{
				var data = Marshal.ReadByte(pNativeData, index++);
				if (data == 0)
				{
					break;
				}
				buffer.Add(data);
			}
			return Encoding.UTF8.GetString(buffer.ToArray());
		}
zq1564171310 2014-11-18
  • 打赏
  • 举报
回复
引用
一个字节一个字节的读取,看看 NULL 在哪里,就可以确定长度了。
请问这个如何实现?
zq1564171310 2014-11-18
  • 打赏
  • 举报
回复
完全没有遇到过,不知如何动手。不过感觉您说的很有道理,即改成了UTF8,又可以确定长度,感觉离目标很近了
zq1564171310 2014-11-18
  • 打赏
  • 举报
回复
... 这个代码不知道怎么实现...
Saleayas 2014-11-18
  • 打赏
  • 举报
回复
一个字节一个字节的读取,看看 NULL 在哪里,就可以确定长度了。
zq1564171310 2014-11-18
  • 打赏
  • 举报
回复
引用 32 楼 Saleayas 的回复:
		object ICustomMarshaler.MarshalNativeToManaged(IntPtr pNativeData)
		{
			List<byte> buffer = new List<byte>();
			int index = 0;
			while (true)
			{
				var data = Marshal.ReadByte(pNativeData, index++);
				if (data == 0)
				{
					break;
				}
				buffer.Add(data);
			}
			return Encoding.UTF8.GetString(buffer.ToArray());
		}
大姐,这个不会用,能指点下么?
wanghui0380 2014-11-17
  • 打赏
  • 举报
回复
长度不匹配很正常,一个汉字是2字节,所以你采用byte[] 传递那么起码他要60字节,才是30个size
zq1564171310 2014-11-17
  • 打赏
  • 举报
回复
没人么?求助!
zq1564171310 2014-11-17
  • 打赏
  • 举报
回复
引用
使用 byte[] 定义成员。 然后,使用 Encoding.UTF8.GetString。 不过我记得好像需要计算 byte[] 的长度。 GetString 好像不能识别 NULL。 所以需要确定 NULL 的位置。 MarshalAs 的 CustomMarshal 好像不能用在结构上,只能用在方法上。
这个有点高深,大侠,请教您:如何确定?
zq1564171310 2014-11-17
  • 打赏
  • 举报
回复
引用
http://www.codeproject.com/Articles/138614/Advanced-Topics-in-PInvoke-String-Marshaling
这篇刷出来了,我曾经看过,一开始我也是用这种方法,但是dll规定了长度,这种自定义的,少了UnmanagedType.ByValArray, SizeConst = 30,无法计算偏移量,单独加上SizeConst = 30,貌似不起什么作用
Saleayas 2014-11-17
  • 打赏
  • 举报
回复
使用 byte[] 定义成员。 然后,使用 Encoding.UTF8.GetString。 不过我记得好像需要计算 byte[] 的长度。 GetString 好像不能识别 NULL。 所以需要确定 NULL 的位置。 MarshalAs 的 CustomMarshal 好像不能用在结构上,只能用在方法上。
zq1564171310 2014-11-17
  • 打赏
  • 举报
回复
引用
https://github.com/openhome/ohLibSpotify/blob/master/src/ohLibSpotify/Utf8String.cs#L99
return SpotifyMarshalling.Utf8ToString(iPtr); 报错,SpotifyMarshalling不存在,这个代码应该不全 另一个界面刷不出来
zq1564171310 2014-11-17
  • 打赏
  • 举报
回复
基本看不懂,unsafe没怎么遇到过,
wanghui0380 2014-11-17
  • 打赏
  • 举报
回复
这里的CustomMarshaler也ok http://www.codeproject.com/Articles/138614/Advanced-Topics-in-PInvoke-String-Marshaling
加载更多回复(19)

111,098

社区成员

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

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

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