首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从Marshal.PtrToStringAnsi返回的字符串的编码是什么?

从Marshal.PtrToStringAnsi返回的字符串的编码是什么?
EN

Stack Overflow用户
提问于 2019-10-15 16:19:39
回答 1查看 1.2K关注 0票数 1

我正在实现一个自定义封送器,将utf8字符串从/发送到本机、从/到托管。

代码语言:javascript
运行
复制
{
    [ComVisible(true)]
    public class UTF8StringMarshaler : ICustomMarshaler
    {
        private static ICustomMarshaler marshalerInstance = new UTF8StringMarshaler();

        public static ICustomMarshaler GetInstance(string optionalCookie)
        {
            return marshalerInstance;
        }
        public void CleanUpManagedData(object ManagedObj)
        {
            //Managed Data will be deleted by the garbage collector
        }

        public void CleanUpNativeData(IntPtr pNativeData)
        {
            Marshal.FreeCoTaskMem(pNativeData);
        }

        public int GetNativeDataSize()
        {
            //Not used in our case
            return -1;
        }

        public IntPtr MarshalManagedToNative(object ManagedObj)
        {
            if (ManagedObj == null || ManagedObj as string == null)
                return IntPtr.Zero;

            if (!(ManagedObj is string))
                throw new MarshalDirectiveException("UTF8StringMarshaler can only be used on String.");

            UTF8Encoding utf8Encoder = new UTF8Encoding();
            string utf8string = ManagedObj as string;
            byte[] stringBuffer = utf8Encoder.GetBytes(utf8string);
            IntPtr buffer = Marshal.AllocCoTaskMem(stringBuffer.Length + 1);
            Marshal.Copy(stringBuffer, 0, buffer, stringBuffer.Length);
            Marshal.WriteByte(buffer + stringBuffer.Length, 0);
            return buffer;
        }

        public unsafe object MarshalNativeToManaged(IntPtr pNativeData)
        {
            if (pNativeData == IntPtr.Zero)
                return null;
            string temp = null;
            UTF8Encoding utf8Encoder = new UTF8Encoding(true, true);
            byte* buffer = (byte*)pNativeData;
            while (*buffer != 0)
            {
                buffer++;
            }
            int length = (int)(buffer - (byte*)pNativeData);

            byte[] stringbuffer = new byte[length];

            Marshal.Copy(pNativeData, stringbuffer, 0, length);
            try
            {
                temp = utf8Encoder.GetString(stringbuffer);
            }
            catch (EncoderFallbackException e)
            {
                Console.WriteLine("Encoding Exception type {0}, Error {1}", e.GetType().Name, e.Message);
            }
            return temp;
        }
    }

此实现可以工作,除非C#字符串来自Marshal.PtrToStringAnsi函数。

所以在MarshalNativeToManaged函数中,我需要验证字符串是否是来自Marshal.PtrToStringAnsi的正确编码。

从Microsoft,Marshal.PtrToStringAnsi将每个ANSI字符扩展到Unicode:

Copies all characters up to the first null character from an unmanaged ANSI string to a managed String, and widens each ANSI character to Unicode.

所以问题是,Marshal.PtrToStringAnsi函数中字符串的编码是什么?

是否有更简单的方法来验证字符串是否来自该函数?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-15 18:41:44

来自Marshal.PtrToStringAnsi函数的字符串编码是什么?

没有"ANSI“编码。无论您的系统的当前代码页是什么,它都是。它将取决于用户的区域设置。这应该与CharSet enum相对应

Ansi:Marshal字符串作为多字节字符串:系统默认 (ANSI)代码页在Windows上,UTF-8在Unix上。

请注意Unix上的特殊处理(我猜想,Linux也是如此)。

是否有更简单的方法来验证字符串是否来自该函数?

在我看来,这似乎是一个与主要问题完全不同的问题。特别是:知道函数在从"ANSI“转换到UTF-16 (.NET使用的内部文本编码)时将使用什么编码,在我看来并没有导致一种”验证字符串是否来自该函数“的方法。一旦您有了一个C# string对象,它已经被编码为UTF-16。它可能起源于几乎所有的编码。

从您的问题中也不清楚您所说的“工作”是什么意思,除非C#字符串来自Marshal.PtrToStringAnsi函数。也就是说,在这种情况下,它究竟用什么方式不起作用呢?您的编组程序似乎只负责将UTF-8字节传递给或从本机代码中传递。给定一个C# string对象,应该不会在意如何创建string。它现在是一个字符串的UTF-16字符,可以可靠地重新编码为UTF-8.如果"ANSI“文本有问题,该问题发生在您的封送员介入之前。你的执法官不应该担心这件事。

最后:为什么不直接使用Encoding.UTF8而不是在每个封送处理操作上实例化一个新的UTF8Encoding对象?至少,您应该缓存对象,但是由于GetBytes()GetString()对于任何UTF8Encoding实例的工作方式都是相同的,所以实际上您应该使用.NET已经为您创建的实例,并让.NET处理缓存对象的问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58398924

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档