解决方案 »

  1.   

    你那个dll到底要string还是char[ ]?还是byte[ ]
      

  2.   

    如果是string,其实跟编码没有关系...直接传就行了
    如果是传入byte[ ] 然后dll自己按UTF-8处理,你就string按UTF-8转byte[ ]传就好了
      

  3.   

    C#中字符串是没有编码之说的,转成byte[]时才会用到编码,就应该是这样做,参数改成byte[]或者intptr.
      

  4.   

    可以明确告诉您,有的!您可以试试在网上搜搜,然后自己试试,我这儿没时间贴代码。
    回复:Z65443344
    我不转化字符串编码,dll收到的就是乱码,所以感觉不能随便传。
      

  5.   

    怎么说呢,我觉得是没有编码的问题。
    在网上搜了一下,都是先转到byte在转到其他的编码。
    你试下反编译BLL,在用把BLL写成的类方式试下
      

  6.   

    那个dll是我自己写的,但是内容是抄的网上别人写的,所以不是很懂,只知道要传一个UTF8的参数给dll。至于将dll重写成类,我没有想过,也不想去试,有点多,太费时间了,所以改dll有点难,只有在C#传参上面做文章了。还请大神指导!
      

  7.   


    你应该先说明,什么叫做“一个UTF8的参数”。请你给出范例。要注意,.net平台里的字符串都是unicode编码的。
      

  8.   

    你只需要修改DLL的一行代码
    就是传参不要传string,而是传入byte[ ],然后再自己转string
    外部按UTF-8转byte[ ]传入DLL的方法里,就行了
      

  9.   

    这个参数变了,相应的函数处理也要变,而函数处理...我抄的,看不懂。
        虽然我不太懂编码,也几乎没有研究过,所以导致今天的困扰。对于您说的“.net平台里的字符串都是unicode编码”,我个人觉得调用dll,String类型默认是ANSI编码(因为我调用System.Text.Encoding.Default时候,鼠标放在Default上,出现的是ANSI)。
        至于范例:就是string str = “ 中国 ”,将str当做参数传给dll某个函数,而str必须是UTF8编码。否则,程序不执行那个函数,dll输出打印的信息为“参数不正确!”
      

  10.   

    我是说,你只修改传入的参数,具体参与处理还用string,但是是另一个局部变量,而不直接使用传入的参数
    这样不就好控制了么.
      

  11.   

    比如我的函数要求传入一个"2",然后参与处理
    现在我传入"2",它就变成了"5"
    那我先传入一个int型的2,dll自己将2转换成"2",然后再继续处理.
    就是这个意思
      

  12.   

    具体参与逻辑的地方,连变量名都不用改
    比如原先的函数是这样的:
    void function(string s)
    {
    s...s...s....各种地方都用到s
    }
    我现在改成这样:
    void function(byte[ ] b)
    {
    s=b(当然不是这么简单,要用对应的编码转)
    s...s...后面依然还用s,什么都不用改
    }
      

  13.   

    同意楼上的,DLL里面的函数,不需要你改动的,只需要在第一行加一个转换, 将byte[]转成String。
      

  14.   

    感谢:Z65443344
    但我还是想用C#来解决问题,因为C我只懂一点基本语法,可以说基本不会。而且我也遇到过dll由别人编写的情况,虽然那时候不需要考虑编码,但难保以后不会遇到,到时候总不能指望别人帮我把dll改了吧!所以我想从C#的角度解决该问题。
      

  15.   

    我已经能够将汉字传给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能够识别,程序能够运行。
    但是遇见了意外:如果传的字符串是英文,且最后一个是数字,那么最后那个数字不能识别,变成“?”
    如果传的字符串中有符号,最后一个字符也变成“?”
    不知道怎么解决?
    求助!!
      

  16.   

    简单的做传byte[]或者IntPtr就可以了。
    如果要好看传string,则比较复杂,要做CustomMarshaling。[DllImport(...)]
    extern static MyCall(byte[] str);void Test()
    {
        byte[] str = Encoding.UTF8.GetBytes("中国 ");
        MyCall(str);
    }
      

  17.   

    额,楼上大哥,求教CustomMarshaling是什么东东?怎么整?
    至于传byte数组,我从来没有考虑过,也不打算考虑。
    我现在不急着等结果,但我更希望能学到东西,以后遇到会多一种解决方式。
    那个CustomMarshaling怎么搞?有资料吗?网站?连接?我想了解了解。
      

  18.   

    可以明确告诉您,有的!您可以试试在网上搜搜,然后自己试试,我这儿没时间贴代码。
    回复: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 此时已经是乱码了....
      

  19.   

        其实此时没有乱码,只是转成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我想研究研究,感觉有戏!
      

  20.   

        还有一个问题:能不能将charset自定义成utf8(.net中charset只有四种枚举,ASNI,None,Auto和unicode,没有utf8,虽然unicode包含utf8,但是Windows中unicode默认是utf16,还是有区别的)。如果能将charset自定义成utf8的话,就简单了,一切问题迎刃而解了。但是我搜了很久,没有类似的记录,有人知道吗?
      

  21.   

    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);
        }
    }
      

  22.   

    字符串只有在转换为字节序列的时候,才有编码一说。
    所以 C++ 的 dll 要求的不是 C# 里面的 string,而是 byte[],所以要重新定义 Dll 的导出函数。
    这样,使用 Encoding 转换为 UTF8 的 字节序列,直接传递给 Dll。
      

  23.   

    String 类  
    表示文本,即一系列 Unicode 字符。
      

  24.   

        下面纯属个人编程感觉:
         对于“字符串只有在转换为字节序列的时候,才有编码一说。”个人不太认同,因为.net平台自动将编码转换,编码统一,让我们少了很多麻烦,同时也让我们误解,字符串没有编码一说。
              至于您说的传byte[ ],虽然现在我可以这么做,但是日后团队开发怎么办?团队不会为您一个人去改dll接口,每个人都有自己的分工,他只要UTF8的字符串,您就只能传字符串。其他人不会为您一个人该接口,甚至您都不知道找谁去修改。
          我没有点评您什么,只是单纯的想解决这个情况,为今后做打算,我希望我能进步,也希望以后看到这封帖子的人有个参考。因为我之前花了不少时间找相关的资料,但是没什么结果。     
           不过,感谢您的参与,让这封帖子多了一分生气。
         
      

  25.   

    回复:gomoku有异常,我尝试解决,但是说实话,您的代码太高深,看不懂,解决不了。
      

  26.   

    团队开发,就必须考虑通用性
    不同开发语言,不同编码格式,必须找一个共有的类型来传递否则我就写成你必须传一个datatable进来,你要使用VC或VB,还没法调用了.
      

  27.   

    对,团队开发一般通用编码UTF8,因为他应用最广。
      

  28.   

    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;
        }
        // 以上添加
      

  29.   

    void Test()
    {
        byte[] str = Encoding.UTF8.GetBytes("中国" + (char)0);   // 更正,要加结束零。
        MyCall(str);
    }
    跟ICustomMarshaler比,你觉得那个更简单?
      

  30.   

         与传递byte数组而言,我更喜欢ICustomMarshaler,因为他可以让我多一种处理方法,个人觉得我们是程序员,有些甚至是工程师,还有些甚至更牛X的。我们这些研发人员不是要求别人去改接口,而是需要自己动手解决问题,这才叫研发人员。
         感谢gomoku,感谢Z65443344,感谢诸位,问题好像解决了,我还需要进一步测试。
         该给分了,人人有份,当然,有人多,有人少,结贴了!