2.string str = “ 中国 ”;如何处理?
被调用的dll只认UTF8,所以C#这边怎么处理参数,才不会乱码,求真大神,别粘贴网上的,那些能转UTF8,但是传给dll,压根儿不识别,我尝试将charset属性改了,但是没有收获,求救!
分不多,给高分我也不甘心,毕竟研究了蛮久,觉得快出结果了,但是好像差那么一点点,哪位大神指点那一点点!
35 个解决方案
#1
你那个dll到底要string还是char[ ]?还是byte[ ]
#2
如果是string,其实跟编码没有关系...直接传就行了
如果是传入byte[ ] 然后dll自己按UTF-8处理,你就string按UTF-8转byte[ ]传就好了
如果是传入byte[ ] 然后dll自己按UTF-8处理,你就string按UTF-8转byte[ ]传就好了
#3
C#中字符串是没有编码之说的,转成byte[]时才会用到编码,就应该是这样做,参数改成byte[]或者intptr.
#4
可以明确告诉您,有的!您可以试试在网上搜搜,然后自己试试,我这儿没时间贴代码。
回复:Z65443344
我不转化字符串编码,dll收到的就是乱码,所以感觉不能随便传。
#5
怎么说呢,我觉得是没有编码的问题。
在网上搜了一下,都是先转到byte在转到其他的编码。
你试下反编译BLL,在用把BLL写成的类方式试下
在网上搜了一下,都是先转到byte在转到其他的编码。
你试下反编译BLL,在用把BLL写成的类方式试下
#6
那个dll是我自己写的,但是内容是抄的网上别人写的,所以不是很懂,只知道要传一个UTF8的参数给dll。至于将dll重写成类,我没有想过,也不想去试,有点多,太费时间了,所以改dll有点难,只有在C#传参上面做文章了。还请大神指导!
#7
Encoding.
#8
你应该先说明,什么叫做“一个UTF8的参数”。请你给出范例。
要注意,.net平台里的字符串都是unicode编码的。
#9
你只需要修改DLL的一行代码
就是传参不要传string,而是传入byte[ ],然后再自己转string
外部按UTF-8转byte[ ]传入DLL的方法里,就行了
就是传参不要传string,而是传入byte[ ],然后再自己转string
外部按UTF-8转byte[ ]传入DLL的方法里,就行了
#10
这个参数变了,相应的函数处理也要变,而函数处理...我抄的,看不懂。
虽然我不太懂编码,也几乎没有研究过,所以导致今天的困扰。对于您说的“.net平台里的字符串都是unicode编码”,我个人觉得调用dll,String类型默认是ANSI编码(因为我调用System.Text.Encoding.Default时候,鼠标放在Default上,出现的是ANSI)。
至于范例:就是string str = “ 中国 ”,将str当做参数传给dll某个函数,而str必须是UTF8编码。否则,程序不执行那个函数,dll输出打印的信息为“参数不正确!”
#11
我是说,你只修改传入的参数,具体参与处理还用string,但是是另一个局部变量,而不直接使用传入的参数
这样不就好控制了么.
这样不就好控制了么.
#12
比如我的函数要求传入一个"2",然后参与处理
现在我传入"2",它就变成了"5"
那我先传入一个int型的2,dll自己将2转换成"2",然后再继续处理.
就是这个意思
现在我传入"2",它就变成了"5"
那我先传入一个int型的2,dll自己将2转换成"2",然后再继续处理.
就是这个意思
#13
具体参与逻辑的地方,连变量名都不用改
比如原先的函数是这样的:
void function(string s)
{
s...s...s....各种地方都用到s
}
我现在改成这样:
void function(byte[ ] b)
{
s=b(当然不是这么简单,要用对应的编码转)
s...s...后面依然还用s,什么都不用改
}
比如原先的函数是这样的:
void function(string s)
{
s...s...s....各种地方都用到s
}
我现在改成这样:
void function(byte[ ] b)
{
s=b(当然不是这么简单,要用对应的编码转)
s...s...后面依然还用s,什么都不用改
}
#14
同意楼上的,DLL里面的函数,不需要你改动的,只需要在第一行加一个转换, 将byte[]转成String。
#15
感谢:Z65443344
但我还是想用C#来解决问题,因为C我只懂一点基本语法,可以说基本不会。而且我也遇到过dll由别人编写的情况,虽然那时候不需要考虑编码,但难保以后不会遇到,到时候总不能指望别人帮我把dll改了吧!所以我想从C#的角度解决该问题。
但我还是想用C#来解决问题,因为C我只懂一点基本语法,可以说基本不会。而且我也遇到过dll由别人编写的情况,虽然那时候不需要考虑编码,但难保以后不会遇到,到时候总不能指望别人帮我把dll改了吧!所以我想从C#的角度解决该问题。
#16
我已经能够将汉字传给dll,但是出现点问题,转化代码如下:
charset设置为unicode,然后:
static string str = System.Text.Encoding.unicode.GetString(System.Text.Encoding.Convert(System.Text.Encoding.Unicode,System.Text.Encoding.UTF8, System.Text.Encoding.Unicode.GetBytes("中国")));
dll能够打印“中国”,虽然输出上是乱码,但是dll能够识别,程序能够运行。
但是遇见了意外:如果传的字符串是英文,且最后一个是数字,那么最后那个数字不能识别,变成“?”
如果传的字符串中有符号,最后一个字符也变成“?”
不知道怎么解决?
求助!!
charset设置为unicode,然后:
static string str = System.Text.Encoding.unicode.GetString(System.Text.Encoding.Convert(System.Text.Encoding.Unicode,System.Text.Encoding.UTF8, System.Text.Encoding.Unicode.GetBytes("中国")));
dll能够打印“中国”,虽然输出上是乱码,但是dll能够识别,程序能够运行。
但是遇见了意外:如果传的字符串是英文,且最后一个是数字,那么最后那个数字不能识别,变成“?”
如果传的字符串中有符号,最后一个字符也变成“?”
不知道怎么解决?
求助!!
#17
简单的做传byte[]或者IntPtr就可以了。
如果要好看传string,则比较复杂,要做CustomMarshaling。
如果要好看传string,则比较复杂,要做CustomMarshaling。
[DllImport(...)]
extern static MyCall(byte[] str);
void Test()
{
byte[] str = Encoding.UTF8.GetBytes("中国 ");
MyCall(str);
}
#18
额,楼上大哥,求教CustomMarshaling是什么东东?怎么整?
至于传byte数组,我从来没有考虑过,也不打算考虑。
我现在不急着等结果,但我更希望能学到东西,以后遇到会多一种解决方式。
那个CustomMarshaling怎么搞?有资料吗?网站?连接?我想了解了解。
至于传byte数组,我从来没有考虑过,也不打算考虑。
我现在不急着等结果,但我更希望能学到东西,以后遇到会多一种解决方式。
那个CustomMarshaling怎么搞?有资料吗?网站?连接?我想了解了解。
#19
string转到byte在转到utf
#20
层主的意思你都没明白就开始胡乱否定...
static string str = System.Text.Encoding.unicode.GetString(System.Text.Encoding.Convert(System.Text.Encoding.Unicode,System.Text.Encoding.UTF8, System.Text.Encoding.Unicode.GetBytes("中国")));
你的这段代码我已经不想说什么了,先是把string转成Unicode字节形式,然后又转成UTF-8字节形式,然后又通过Unicode转换回string 此时已经是乱码了....
#21
其实此时没有乱码,只是转成unicode字符串的时候,最后一个字符会变成问号。因为unicode遇到连续两个‘\0’,才会认为终止,而static string str = System.Text.Encoding.unicode.GetString(byte【utf8】)只有一个'\0',所以乱码。在全是英文的时候,我加上一个'\0'就没有乱码,但是转中文又乱码了。而转中文不加“\0”,正常,所以,纠结。
http://blog.csdn.net/ikok/article/details/8028803
至于最终转到utf8字符串,我只能呵呵,因为charset = unicode,所以dll压根儿不认识,虽然控制台输出正常,但是dll会认为乱码。
17楼,那个CustomMarshaling我想研究研究,感觉有戏!
http://blog.csdn.net/ikok/article/details/8028803
至于最终转到utf8字符串,我只能呵呵,因为charset = unicode,所以dll压根儿不认识,虽然控制台输出正常,但是dll会认为乱码。
17楼,那个CustomMarshaling我想研究研究,感觉有戏!
#22
还有一个问题:能不能将charset自定义成utf8(.net中charset只有四种枚举,ASNI,None,Auto和unicode,没有utf8,虽然unicode包含utf8,但是Windows中unicode默认是utf16,还是有区别的)。如果能将charset自定义成utf8的话,就简单了,一切问题迎刃而解了。但是我搜了很久,没有类似的记录,有人知道吗?
#23
感觉问题有点难度,所以加分了,大家踊跃发言,虽然我不可能每个人都给到分,但是有道理的,我会尽量做到让您有回报。
#24
class NativeMethods
{
[DllImport("...")]
extern static void MyFunc([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8StringMarshaler))]string str);
}
class UTF8StringMarshaler : ICustomMarshaler
{
public void CleanUpManagedData(object ManagedObj)
{
}
public void CleanUpNativeData(IntPtr pNativeData)
{
Marshal.FreeHGlobal(pNativeData);
}
public int GetNativeDataSize()
{
return -1;
}
public IntPtr MarshalManagedToNative(object ManagedObj)
{
if (object.ReferenceEquals(ManagedObj, null)) return IntPtr.Zero;
if (!(ManagedObj is string)) throw new InvalidOperationException();
byte[] utf8bytes = Encoding.UTF8.GetBytes(ManagedObj as string);
IntPtr ptr = Marshal.AllocHGlobal(utf8bytes.Length + 1);
Marshal.Copy(utf8bytes, 0, ptr, utf8bytes.Length);
Marshal.WriteByte(ptr, utf8bytes.Length, 0);
return ptr;
}
public object MarshalNativeToManaged(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return null;
List<byte> bytes = new List<byte>();
for (int offset = 0; ; offset++)
{
byte b = Marshal.ReadByte(pNativeData, offset);
if (b == 0) break;
else bytes.Add(b);
}
return Encoding.UTF8.GetString(bytes.ToArray(), 0, bytes.Count);
}
}
{
[DllImport("...")]
extern static void MyFunc([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8StringMarshaler))]string str);
}
class UTF8StringMarshaler : ICustomMarshaler
{
public void CleanUpManagedData(object ManagedObj)
{
}
public void CleanUpNativeData(IntPtr pNativeData)
{
Marshal.FreeHGlobal(pNativeData);
}
public int GetNativeDataSize()
{
return -1;
}
public IntPtr MarshalManagedToNative(object ManagedObj)
{
if (object.ReferenceEquals(ManagedObj, null)) return IntPtr.Zero;
if (!(ManagedObj is string)) throw new InvalidOperationException();
byte[] utf8bytes = Encoding.UTF8.GetBytes(ManagedObj as string);
IntPtr ptr = Marshal.AllocHGlobal(utf8bytes.Length + 1);
Marshal.Copy(utf8bytes, 0, ptr, utf8bytes.Length);
Marshal.WriteByte(ptr, utf8bytes.Length, 0);
return ptr;
}
public object MarshalNativeToManaged(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return null;
List<byte> bytes = new List<byte>();
for (int offset = 0; ; offset++)
{
byte b = Marshal.ReadByte(pNativeData, offset);
if (b == 0) break;
else bytes.Add(b);
}
return Encoding.UTF8.GetString(bytes.ToArray(), 0, bytes.Count);
}
}
#25
字符串只有在转换为字节序列的时候,才有编码一说。
所以 C++ 的 dll 要求的不是 C# 里面的 string,而是 byte[],所以要重新定义 Dll 的导出函数。
这样,使用 Encoding 转换为 UTF8 的 字节序列,直接传递给 Dll。
所以 C++ 的 dll 要求的不是 C# 里面的 string,而是 byte[],所以要重新定义 Dll 的导出函数。
这样,使用 Encoding 转换为 UTF8 的 字节序列,直接传递给 Dll。
#26
c#中的string就是UTF8
#27
String 类
表示文本,即一系列 Unicode 字符。
表示文本,即一系列 Unicode 字符。
#28
字符串只有在转换为字节序列的时候,才有编码一说。
所以 C++ 的 dll 要求的不是 C# 里面的 string,而是 byte[],所以要重新定义 Dll 的导出函数。
这样,使用 Encoding 转换为 UTF8 的 字节序列,直接传递给 Dll。
下面纯属个人编程感觉:
对于“字符串只有在转换为字节序列的时候,才有编码一说。”个人不太认同,因为.net平台自动将编码转换,编码统一,让我们少了很多麻烦,同时也让我们误解,字符串没有编码一说。
至于您说的传byte[ ],虽然现在我可以这么做,但是日后团队开发怎么办?团队不会为您一个人去改dll接口,每个人都有自己的分工,他只要UTF8的字符串,您就只能传字符串。其他人不会为您一个人该接口,甚至您都不知道找谁去修改。
我没有点评您什么,只是单纯的想解决这个情况,为今后做打算,我希望我能进步,也希望以后看到这封帖子的人有个参考。因为我之前花了不少时间找相关的资料,但是没什么结果。
不过,感谢您的参与,让这封帖子多了一分生气。
#29
回复:gomoku
有异常,我尝试解决,但是说实话,您的代码太高深,看不懂,解决不了。
有异常,我尝试解决,但是说实话,您的代码太高深,看不懂,解决不了。
未经处理的异常:
自定义封送拆收器“XXX.UTF8stringMarshaler”不实现采用单个字符串参数并返回IcustomMarshaler的静态GetInstance方法。
#30
团队开发,就必须考虑通用性
不同开发语言,不同编码格式,必须找一个共有的类型来传递
否则我就写成你必须传一个datatable进来,你要使用VC或VB,还没法调用了.
不同开发语言,不同编码格式,必须找一个共有的类型来传递
否则我就写成你必须传一个datatable进来,你要使用VC或VB,还没法调用了.
#31
对,团队开发一般通用编码UTF8,因为他应用最广。
#32
字符串可以直接传啊,字节的要看编码格式了~~楼主调试下不就可以了吗?何必那么纠结
#33
class UTF8StringMarshaler : ICustomMarshaler
{
public void CleanUpManagedData(object ManagedObj)
{
}
public void CleanUpNativeData(IntPtr pNativeData)
{
Marshal.FreeHGlobal(pNativeData);
}
public int GetNativeDataSize()
{
return -1;
}
public IntPtr MarshalManagedToNative(object ManagedObj)
{
if (object.ReferenceEquals(ManagedObj, null)) return IntPtr.Zero;
if (!(ManagedObj is string)) throw new InvalidOperationException();
byte[] utf8bytes = Encoding.UTF8.GetBytes(ManagedObj as string);
IntPtr ptr = Marshal.AllocHGlobal(utf8bytes.Length + 1);
Marshal.Copy(utf8bytes, 0, ptr, utf8bytes.Length);
Marshal.WriteByte(ptr, utf8bytes.Length, 0);
return ptr;
}
public object MarshalNativeToManaged(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return null;
List<byte> bytes = new List<byte>();
for (int offset = 0; ; offset++)
{
byte b = Marshal.ReadByte(pNativeData, offset);
if (b == 0) break;
else bytes.Add(b);
}
return Encoding.UTF8.GetString(bytes.ToArray(), 0, bytes.Count);
}
// 添加以下静态GetInstance方法
static UTF8StringMarshaler instance = new UTF8StringMarshaler();
public static ICustomMarshaler GetInstance(string cookie)
{
return instance;
}
// 以上添加
}
#34
简单的做传byte[]或者IntPtr就可以了。
如果要好看传string,则比较复杂,要做CustomMarshaling。[DllImport(...)]
extern static MyCall(byte[] str);
void Test()
{
byte[] str = Encoding.UTF8.GetBytes("中国 ");
MyCall(str);
}
void Test()
{
byte[] str = Encoding.UTF8.GetBytes("中国" + (char)0); // 更正,要加结束零。
MyCall(str);
}
跟ICustomMarshaler比,你觉得那个更简单?
#35
与传递byte数组而言,我更喜欢ICustomMarshaler,因为他可以让我多一种处理方法,个人觉得我们是程序员,有些甚至是工程师,还有些甚至更牛X的。我们这些研发人员不是要求别人去改接口,而是需要自己动手解决问题,这才叫研发人员。
感谢gomoku,感谢Z65443344,感谢诸位,问题好像解决了,我还需要进一步测试。
该给分了,人人有份,当然,有人多,有人少,结贴了!
感谢gomoku,感谢Z65443344,感谢诸位,问题好像解决了,我还需要进一步测试。
该给分了,人人有份,当然,有人多,有人少,结贴了!
#1
你那个dll到底要string还是char[ ]?还是byte[ ]
#2
如果是string,其实跟编码没有关系...直接传就行了
如果是传入byte[ ] 然后dll自己按UTF-8处理,你就string按UTF-8转byte[ ]传就好了
如果是传入byte[ ] 然后dll自己按UTF-8处理,你就string按UTF-8转byte[ ]传就好了
#3
C#中字符串是没有编码之说的,转成byte[]时才会用到编码,就应该是这样做,参数改成byte[]或者intptr.
#4
C#中字符串是没有编码之说的
可以明确告诉您,有的!您可以试试在网上搜搜,然后自己试试,我这儿没时间贴代码。
回复:Z65443344
我不转化字符串编码,dll收到的就是乱码,所以感觉不能随便传。
#5
怎么说呢,我觉得是没有编码的问题。
在网上搜了一下,都是先转到byte在转到其他的编码。
你试下反编译BLL,在用把BLL写成的类方式试下
在网上搜了一下,都是先转到byte在转到其他的编码。
你试下反编译BLL,在用把BLL写成的类方式试下
#6
那个dll是我自己写的,但是内容是抄的网上别人写的,所以不是很懂,只知道要传一个UTF8的参数给dll。至于将dll重写成类,我没有想过,也不想去试,有点多,太费时间了,所以改dll有点难,只有在C#传参上面做文章了。还请大神指导!
#7
Encoding.
#8
那个dll是我自己写的,但是内容是抄的网上别人写的,所以不是很懂,只知道要传一个UTF8的参数给dll。至于将dll重写成类,我没有想过,也不想去试,有点多,太费时间了,所以改dll有点难,只有在C#传参上面做文章了。还请大神指导!
你应该先说明,什么叫做“一个UTF8的参数”。请你给出范例。
要注意,.net平台里的字符串都是unicode编码的。
#9
你只需要修改DLL的一行代码
就是传参不要传string,而是传入byte[ ],然后再自己转string
外部按UTF-8转byte[ ]传入DLL的方法里,就行了
就是传参不要传string,而是传入byte[ ],然后再自己转string
外部按UTF-8转byte[ ]传入DLL的方法里,就行了
#10
你只需要修改DLL的一行代码
就是传参不要传string,而是传入byte[ ],然后再自己转string
外部按UTF-8转byte[ ]传入DLL的方法里,就行了
这个参数变了,相应的函数处理也要变,而函数处理...我抄的,看不懂。
你应该先说明,什么叫做“一个UTF8的参数”。请你给出范例。
要注意,.net平台里的字符串都是unicode编码的。
虽然我不太懂编码,也几乎没有研究过,所以导致今天的困扰。对于您说的“.net平台里的字符串都是unicode编码”,我个人觉得调用dll,String类型默认是ANSI编码(因为我调用System.Text.Encoding.Default时候,鼠标放在Default上,出现的是ANSI)。
至于范例:就是string str = “ 中国 ”,将str当做参数传给dll某个函数,而str必须是UTF8编码。否则,程序不执行那个函数,dll输出打印的信息为“参数不正确!”
#11
我是说,你只修改传入的参数,具体参与处理还用string,但是是另一个局部变量,而不直接使用传入的参数
这样不就好控制了么.
这样不就好控制了么.
#12
比如我的函数要求传入一个"2",然后参与处理
现在我传入"2",它就变成了"5"
那我先传入一个int型的2,dll自己将2转换成"2",然后再继续处理.
就是这个意思
现在我传入"2",它就变成了"5"
那我先传入一个int型的2,dll自己将2转换成"2",然后再继续处理.
就是这个意思
#13
具体参与逻辑的地方,连变量名都不用改
比如原先的函数是这样的:
void function(string s)
{
s...s...s....各种地方都用到s
}
我现在改成这样:
void function(byte[ ] b)
{
s=b(当然不是这么简单,要用对应的编码转)
s...s...后面依然还用s,什么都不用改
}
比如原先的函数是这样的:
void function(string s)
{
s...s...s....各种地方都用到s
}
我现在改成这样:
void function(byte[ ] b)
{
s=b(当然不是这么简单,要用对应的编码转)
s...s...后面依然还用s,什么都不用改
}
#14
同意楼上的,DLL里面的函数,不需要你改动的,只需要在第一行加一个转换, 将byte[]转成String。
#15
感谢:Z65443344
但我还是想用C#来解决问题,因为C我只懂一点基本语法,可以说基本不会。而且我也遇到过dll由别人编写的情况,虽然那时候不需要考虑编码,但难保以后不会遇到,到时候总不能指望别人帮我把dll改了吧!所以我想从C#的角度解决该问题。
但我还是想用C#来解决问题,因为C我只懂一点基本语法,可以说基本不会。而且我也遇到过dll由别人编写的情况,虽然那时候不需要考虑编码,但难保以后不会遇到,到时候总不能指望别人帮我把dll改了吧!所以我想从C#的角度解决该问题。
#16
我已经能够将汉字传给dll,但是出现点问题,转化代码如下:
charset设置为unicode,然后:
static string str = System.Text.Encoding.unicode.GetString(System.Text.Encoding.Convert(System.Text.Encoding.Unicode,System.Text.Encoding.UTF8, System.Text.Encoding.Unicode.GetBytes("中国")));
dll能够打印“中国”,虽然输出上是乱码,但是dll能够识别,程序能够运行。
但是遇见了意外:如果传的字符串是英文,且最后一个是数字,那么最后那个数字不能识别,变成“?”
如果传的字符串中有符号,最后一个字符也变成“?”
不知道怎么解决?
求助!!
charset设置为unicode,然后:
static string str = System.Text.Encoding.unicode.GetString(System.Text.Encoding.Convert(System.Text.Encoding.Unicode,System.Text.Encoding.UTF8, System.Text.Encoding.Unicode.GetBytes("中国")));
dll能够打印“中国”,虽然输出上是乱码,但是dll能够识别,程序能够运行。
但是遇见了意外:如果传的字符串是英文,且最后一个是数字,那么最后那个数字不能识别,变成“?”
如果传的字符串中有符号,最后一个字符也变成“?”
不知道怎么解决?
求助!!
#17
简单的做传byte[]或者IntPtr就可以了。
如果要好看传string,则比较复杂,要做CustomMarshaling。
如果要好看传string,则比较复杂,要做CustomMarshaling。
[DllImport(...)]
extern static MyCall(byte[] str);
void Test()
{
byte[] str = Encoding.UTF8.GetBytes("中国 ");
MyCall(str);
}
#18
额,楼上大哥,求教CustomMarshaling是什么东东?怎么整?
至于传byte数组,我从来没有考虑过,也不打算考虑。
我现在不急着等结果,但我更希望能学到东西,以后遇到会多一种解决方式。
那个CustomMarshaling怎么搞?有资料吗?网站?连接?我想了解了解。
至于传byte数组,我从来没有考虑过,也不打算考虑。
我现在不急着等结果,但我更希望能学到东西,以后遇到会多一种解决方式。
那个CustomMarshaling怎么搞?有资料吗?网站?连接?我想了解了解。
#19
string转到byte在转到utf
#20
C#中字符串是没有编码之说的
可以明确告诉您,有的!您可以试试在网上搜搜,然后自己试试,我这儿没时间贴代码。
回复:Z65443344
我不转化字符串编码,dll收到的就是乱码,所以感觉不能随便传。
层主的意思你都没明白就开始胡乱否定...
static string str = System.Text.Encoding.unicode.GetString(System.Text.Encoding.Convert(System.Text.Encoding.Unicode,System.Text.Encoding.UTF8, System.Text.Encoding.Unicode.GetBytes("中国")));
你的这段代码我已经不想说什么了,先是把string转成Unicode字节形式,然后又转成UTF-8字节形式,然后又通过Unicode转换回string 此时已经是乱码了....
#21
其实此时没有乱码,只是转成unicode字符串的时候,最后一个字符会变成问号。因为unicode遇到连续两个‘\0’,才会认为终止,而static string str = System.Text.Encoding.unicode.GetString(byte【utf8】)只有一个'\0',所以乱码。在全是英文的时候,我加上一个'\0'就没有乱码,但是转中文又乱码了。而转中文不加“\0”,正常,所以,纠结。
http://blog.csdn.net/ikok/article/details/8028803
至于最终转到utf8字符串,我只能呵呵,因为charset = unicode,所以dll压根儿不认识,虽然控制台输出正常,但是dll会认为乱码。
17楼,那个CustomMarshaling我想研究研究,感觉有戏!
http://blog.csdn.net/ikok/article/details/8028803
至于最终转到utf8字符串,我只能呵呵,因为charset = unicode,所以dll压根儿不认识,虽然控制台输出正常,但是dll会认为乱码。
17楼,那个CustomMarshaling我想研究研究,感觉有戏!
#22
还有一个问题:能不能将charset自定义成utf8(.net中charset只有四种枚举,ASNI,None,Auto和unicode,没有utf8,虽然unicode包含utf8,但是Windows中unicode默认是utf16,还是有区别的)。如果能将charset自定义成utf8的话,就简单了,一切问题迎刃而解了。但是我搜了很久,没有类似的记录,有人知道吗?
#23
感觉问题有点难度,所以加分了,大家踊跃发言,虽然我不可能每个人都给到分,但是有道理的,我会尽量做到让您有回报。
#24
class NativeMethods
{
[DllImport("...")]
extern static void MyFunc([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8StringMarshaler))]string str);
}
class UTF8StringMarshaler : ICustomMarshaler
{
public void CleanUpManagedData(object ManagedObj)
{
}
public void CleanUpNativeData(IntPtr pNativeData)
{
Marshal.FreeHGlobal(pNativeData);
}
public int GetNativeDataSize()
{
return -1;
}
public IntPtr MarshalManagedToNative(object ManagedObj)
{
if (object.ReferenceEquals(ManagedObj, null)) return IntPtr.Zero;
if (!(ManagedObj is string)) throw new InvalidOperationException();
byte[] utf8bytes = Encoding.UTF8.GetBytes(ManagedObj as string);
IntPtr ptr = Marshal.AllocHGlobal(utf8bytes.Length + 1);
Marshal.Copy(utf8bytes, 0, ptr, utf8bytes.Length);
Marshal.WriteByte(ptr, utf8bytes.Length, 0);
return ptr;
}
public object MarshalNativeToManaged(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return null;
List<byte> bytes = new List<byte>();
for (int offset = 0; ; offset++)
{
byte b = Marshal.ReadByte(pNativeData, offset);
if (b == 0) break;
else bytes.Add(b);
}
return Encoding.UTF8.GetString(bytes.ToArray(), 0, bytes.Count);
}
}
{
[DllImport("...")]
extern static void MyFunc([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8StringMarshaler))]string str);
}
class UTF8StringMarshaler : ICustomMarshaler
{
public void CleanUpManagedData(object ManagedObj)
{
}
public void CleanUpNativeData(IntPtr pNativeData)
{
Marshal.FreeHGlobal(pNativeData);
}
public int GetNativeDataSize()
{
return -1;
}
public IntPtr MarshalManagedToNative(object ManagedObj)
{
if (object.ReferenceEquals(ManagedObj, null)) return IntPtr.Zero;
if (!(ManagedObj is string)) throw new InvalidOperationException();
byte[] utf8bytes = Encoding.UTF8.GetBytes(ManagedObj as string);
IntPtr ptr = Marshal.AllocHGlobal(utf8bytes.Length + 1);
Marshal.Copy(utf8bytes, 0, ptr, utf8bytes.Length);
Marshal.WriteByte(ptr, utf8bytes.Length, 0);
return ptr;
}
public object MarshalNativeToManaged(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return null;
List<byte> bytes = new List<byte>();
for (int offset = 0; ; offset++)
{
byte b = Marshal.ReadByte(pNativeData, offset);
if (b == 0) break;
else bytes.Add(b);
}
return Encoding.UTF8.GetString(bytes.ToArray(), 0, bytes.Count);
}
}
#25
字符串只有在转换为字节序列的时候,才有编码一说。
所以 C++ 的 dll 要求的不是 C# 里面的 string,而是 byte[],所以要重新定义 Dll 的导出函数。
这样,使用 Encoding 转换为 UTF8 的 字节序列,直接传递给 Dll。
所以 C++ 的 dll 要求的不是 C# 里面的 string,而是 byte[],所以要重新定义 Dll 的导出函数。
这样,使用 Encoding 转换为 UTF8 的 字节序列,直接传递给 Dll。
#26
c#中的string就是UTF8
#27
String 类
表示文本,即一系列 Unicode 字符。
表示文本,即一系列 Unicode 字符。
#28
字符串只有在转换为字节序列的时候,才有编码一说。
所以 C++ 的 dll 要求的不是 C# 里面的 string,而是 byte[],所以要重新定义 Dll 的导出函数。
这样,使用 Encoding 转换为 UTF8 的 字节序列,直接传递给 Dll。
下面纯属个人编程感觉:
对于“字符串只有在转换为字节序列的时候,才有编码一说。”个人不太认同,因为.net平台自动将编码转换,编码统一,让我们少了很多麻烦,同时也让我们误解,字符串没有编码一说。
至于您说的传byte[ ],虽然现在我可以这么做,但是日后团队开发怎么办?团队不会为您一个人去改dll接口,每个人都有自己的分工,他只要UTF8的字符串,您就只能传字符串。其他人不会为您一个人该接口,甚至您都不知道找谁去修改。
我没有点评您什么,只是单纯的想解决这个情况,为今后做打算,我希望我能进步,也希望以后看到这封帖子的人有个参考。因为我之前花了不少时间找相关的资料,但是没什么结果。
不过,感谢您的参与,让这封帖子多了一分生气。
#29
回复:gomoku
有异常,我尝试解决,但是说实话,您的代码太高深,看不懂,解决不了。
有异常,我尝试解决,但是说实话,您的代码太高深,看不懂,解决不了。
未经处理的异常:
自定义封送拆收器“XXX.UTF8stringMarshaler”不实现采用单个字符串参数并返回IcustomMarshaler的静态GetInstance方法。
#30
团队开发,就必须考虑通用性
不同开发语言,不同编码格式,必须找一个共有的类型来传递
否则我就写成你必须传一个datatable进来,你要使用VC或VB,还没法调用了.
不同开发语言,不同编码格式,必须找一个共有的类型来传递
否则我就写成你必须传一个datatable进来,你要使用VC或VB,还没法调用了.
#31
对,团队开发一般通用编码UTF8,因为他应用最广。
#32
字符串可以直接传啊,字节的要看编码格式了~~楼主调试下不就可以了吗?何必那么纠结
#33
class UTF8StringMarshaler : ICustomMarshaler
{
public void CleanUpManagedData(object ManagedObj)
{
}
public void CleanUpNativeData(IntPtr pNativeData)
{
Marshal.FreeHGlobal(pNativeData);
}
public int GetNativeDataSize()
{
return -1;
}
public IntPtr MarshalManagedToNative(object ManagedObj)
{
if (object.ReferenceEquals(ManagedObj, null)) return IntPtr.Zero;
if (!(ManagedObj is string)) throw new InvalidOperationException();
byte[] utf8bytes = Encoding.UTF8.GetBytes(ManagedObj as string);
IntPtr ptr = Marshal.AllocHGlobal(utf8bytes.Length + 1);
Marshal.Copy(utf8bytes, 0, ptr, utf8bytes.Length);
Marshal.WriteByte(ptr, utf8bytes.Length, 0);
return ptr;
}
public object MarshalNativeToManaged(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return null;
List<byte> bytes = new List<byte>();
for (int offset = 0; ; offset++)
{
byte b = Marshal.ReadByte(pNativeData, offset);
if (b == 0) break;
else bytes.Add(b);
}
return Encoding.UTF8.GetString(bytes.ToArray(), 0, bytes.Count);
}
// 添加以下静态GetInstance方法
static UTF8StringMarshaler instance = new UTF8StringMarshaler();
public static ICustomMarshaler GetInstance(string cookie)
{
return instance;
}
// 以上添加
}
#34
简单的做传byte[]或者IntPtr就可以了。
如果要好看传string,则比较复杂,要做CustomMarshaling。[DllImport(...)]
extern static MyCall(byte[] str);
void Test()
{
byte[] str = Encoding.UTF8.GetBytes("中国 ");
MyCall(str);
}
void Test()
{
byte[] str = Encoding.UTF8.GetBytes("中国" + (char)0); // 更正,要加结束零。
MyCall(str);
}
跟ICustomMarshaler比,你觉得那个更简单?
#35
与传递byte数组而言,我更喜欢ICustomMarshaler,因为他可以让我多一种处理方法,个人觉得我们是程序员,有些甚至是工程师,还有些甚至更牛X的。我们这些研发人员不是要求别人去改接口,而是需要自己动手解决问题,这才叫研发人员。
感谢gomoku,感谢Z65443344,感谢诸位,问题好像解决了,我还需要进一步测试。
该给分了,人人有份,当然,有人多,有人少,结贴了!
感谢gomoku,感谢Z65443344,感谢诸位,问题好像解决了,我还需要进一步测试。
该给分了,人人有份,当然,有人多,有人少,结贴了!