Marshal UTF8 Strings in .NET
2015-06-26 16:42
155 查看
原文:
Marshal UTF8 Strings in .NET
Wow, what a pain in the butt. .NET strings are stored internally as UTF16, not UTF8, so if you're marshaling strings to and from a library that wants strings as UTF8, you have to manually
marshal them yourself.
This took me a whole day to figure out why my my .NET wrapper library wasn't working, and a whole other day to figure out how to work around it and debug the code. If this code saves at least one person the amount of time I lost then I'm satisfied.
You'll notice that there's a lot of data copying going on and there are a few copies of string made. Yep, that's because the .NET framework can't just pin the array in memory that stores the string (remember, strings are stored as UTF16 in the .NET framework)
and you have to make the conversion yourself.
Marshal UTF8 Strings in .NET
Marshal UTF8 Strings in .NET
Wow, what a pain in the butt. .NET strings are stored internally as UTF16, not UTF8, so if you're marshaling strings to and from a library that wants strings as UTF8, you have to manuallymarshal them yourself.
This took me a whole day to figure out why my my .NET wrapper library wasn't working, and a whole other day to figure out how to work around it and debug the code. If this code saves at least one person the amount of time I lost then I'm satisfied.
public class MarshalPtrToUtf8 : ICustomMarshaler { static MarshalPtrToUtf8 marshaler = new MarshalPtrToUtf8(); public void CleanUpManagedData(object ManagedObj) { } public void CleanUpNativeData(IntPtr pNativeData) { Marshal.Release(pNativeData); } public int GetNativeDataSize() { return Marshal.SizeOf(typeof(byte)); } public int GetNativeDataSize(IntPtr ptr) { int size = 0; for (size = 0; Marshal.ReadByte(ptr, size) > 0; size++) ; return size; } public IntPtr MarshalManagedToNative(object ManagedObj) { if (ManagedObj == null) return IntPtr.Zero; if (ManagedObj.GetType() != typeof(string)) throw new ArgumentException("ManagedObj", "Can only marshal type of System.String"); byte[] array = Encoding.UTF8.GetBytes((string)ManagedObj); int size = Marshal.SizeOf(array[0]) * array.Length + Marshal.SizeOf(array[0]); IntPtr ptr = Marshal.AllocHGlobal(size); Marshal.Copy(array, 0, ptr, array.Length); Marshal.WriteByte(ptr, size - 1, 0); return ptr; } public object MarshalNativeToManaged(IntPtr pNativeData) { if (pNativeData == IntPtr.Zero) return null; int size = GetNativeDataSize(pNativeData); byte[] array = new byte[size - 1]; Marshal.Copy(pNativeData, array, 0, size - 1); return Encoding.UTF8.GetString(array); } public static ICustomMarshaler GetInstance(string cookie) { return marshaler; } }
You'll notice that there's a lot of data copying going on and there are a few copies of string made. Yep, that's because the .NET framework can't just pin the array in memory that stores the string (remember, strings are stored as UTF16 in the .NET framework)
and you have to make the conversion yourself.
相关文章推荐
- $.extend,$.fn.extend和(function($){...})(jQuery);
- 第三个Sprint完结工作 用场景来规划测试工作.
- cocos2d-x3.6 连连看连通算法
- B树、B-树、B+树、B*树
- Android 触摸事件传递机制
- 《Java并发编程实践》笔记5——线程活跃性问题及其解决方法
- LintCode HashFunction 哈希函数
- 摄像机中的基础矩阵
- SpringMVC常用基础知识
- [ActionScript 3.0] 使用Embed在类中嵌入字体
- leetcode[88]:Merge Sorted Array
- 使用自定义的BaseAdapter实现 onitemclickListener
- 教你如何编写简单的网络爬虫
- setsockopt()函数
- SpringMVC Controller 介绍
- 典型的查询语句
- php 快速排序
- [Selenium] Explicit wait 方法
- console.debug()浏览器控制台打印输出 只在支持console的浏览器下打印
- OpenStack Juno系列之L3 HA agent and VRRP 推荐