C# 传一个参数(带中文的字符串)给dll ,要求传UTF8,怎么传?

时间:2023-01-10 12:27:49
1.charset属性如何设置
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[ ]传就好了

#3


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

#4


引用
C#中字符串是没有编码之说的

可以明确告诉您,有的!您可以试试在网上搜搜,然后自己试试,我这儿没时间贴代码。


回复:Z65443344
我不转化字符串编码,dll收到的就是乱码,所以感觉不能随便传。

#5


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

#6


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

#7


Encoding.

#8


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


你应该先说明,什么叫做“一个UTF8的参数”。请你给出范例。

要注意,.net平台里的字符串都是unicode编码的。

#9


你只需要修改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",然后再继续处理.
就是这个意思

#13


具体参与逻辑的地方,连变量名都不用改
比如原先的函数是这样的:
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#的角度解决该问题。

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

#17


简单的做传byte[]或者IntPtr就可以了。
如果要好看传string,则比较复杂,要做CustomMarshaling。

[DllImport(...)]
extern static MyCall(byte[] str);

void Test()
{
    byte[] str = Encoding.UTF8.GetBytes("中国 ");
    MyCall(str);
}

#18


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

#19


string转到byte在转到utf

#20


引用 4 楼 u014752905 的回复:
引用
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我想研究研究,感觉有戏!

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

#25


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

#26


c#中的string就是UTF8

#27


String 类  
表示文本,即一系列 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,还没法调用了.

#31


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

#32


C# 传一个参数(带中文的字符串)给dll ,要求传UTF8,怎么传?字符串可以直接传啊,字节的要看编码格式了~~楼主调试下不就可以了吗?何必那么纠结

#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


引用 17 楼 gomoku 的回复:
简单的做传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,感谢诸位,问题好像解决了,我还需要进一步测试。
     该给分了,人人有份,当然,有人多,有人少,结贴了!
    

#1


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

#2


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

#3


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

#4


引用
C#中字符串是没有编码之说的

可以明确告诉您,有的!您可以试试在网上搜搜,然后自己试试,我这儿没时间贴代码。


回复:Z65443344
我不转化字符串编码,dll收到的就是乱码,所以感觉不能随便传。

#5


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

#6


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

#7


Encoding.

#8


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


你应该先说明,什么叫做“一个UTF8的参数”。请你给出范例。

要注意,.net平台里的字符串都是unicode编码的。

#9


你只需要修改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",然后再继续处理.
就是这个意思

#13


具体参与逻辑的地方,连变量名都不用改
比如原先的函数是这样的:
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#的角度解决该问题。

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

#17


简单的做传byte[]或者IntPtr就可以了。
如果要好看传string,则比较复杂,要做CustomMarshaling。

[DllImport(...)]
extern static MyCall(byte[] str);

void Test()
{
    byte[] str = Encoding.UTF8.GetBytes("中国 ");
    MyCall(str);
}

#18


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

#19


string转到byte在转到utf

#20


引用 4 楼 u014752905 的回复:
引用
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我想研究研究,感觉有戏!

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

#25


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

#26


c#中的string就是UTF8

#27


String 类  
表示文本,即一系列 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,还没法调用了.

#31


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

#32


C# 传一个参数(带中文的字符串)给dll ,要求传UTF8,怎么传?字符串可以直接传啊,字节的要看编码格式了~~楼主调试下不就可以了吗?何必那么纠结

#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


引用 17 楼 gomoku 的回复:
简单的做传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,感谢诸位,问题好像解决了,我还需要进一步测试。
     该给分了,人人有份,当然,有人多,有人少,结贴了!