原文: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 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.

        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.

Marshal UTF8 Strings in .NET的更多相关文章

  1. » Working Around JNI UTF-8 Strings Deprogramming

    private static native void printString(String text); ... void examplePrintString() { String str = &q ...

  2. About using UTF-8 fields in MySQL

    https://www.adayinthelifeof.nl/2010/12/04/about-using-utf-8-fields-in-mysql/ I sometimes hear: “make ...

  3. PHP 与 UTF-8

    没有一行式解决方案.小心.注意细节,以及一致性. PHP 中的 UTF-8 糟透了.原谅我的用词. 目前 PHP 在低层次上还不支持 Unicode.有几种方式可以确保 UTF-8 字符串能够被正确处 ...

  4. CI框架源码学习笔记7——Utf8.php

    愉快的清明节假期结束了,继续回到CI框架学习.这一节我们来看看Utf8.php文件,它主要是用来做utf8编码,废话不多说,上代码. class CI_Utf8 { /** * Class const ...

  5. utf8 string

    https://github.com/BassLC/idUTF8lib Idiot's UTF-8 Library A very (too much really) simple Utf8 libra ...

  6. Go package(2) strings 用法

    go version go1.10.3 Go中的字符串用法,可以在 godoc.org 上查看语法和用法. 最简单的语法就是获取字符串中的子串 s := "hello world" ...

  7. Vulkan(1)用apispec生成Vulkan库

    Vulkan(1)用apispec生成Vulkan库 我的Vulkan.net库已在(https://github.com/bitzhuwei/Vulkan.net)开源,欢迎交流. apispec. ...

  8. Thinking in Java——笔记(18)

    I/O The original byte-oriented library was supplemented with char-oriented, Unicode-based I/O classe ...

  9. PHP正则表达式模式修饰符 /i, /is, /s, /isU等

    模式修饰符 下面列出了当前可用的 PCRE 修饰符.括号中提到的名字是 PCRE 内部这些修饰符的名称. 模式修饰符中的空格,换行符会被忽略,其他字符会导致错误. i (PCRE_CASELESS) ...

随机推荐

  1. 深入探究VC —— 链接器link.exe(4)

    在程序编译完成后,生成的文件是以.obj为扩展名的对象文件,link.exe是将这些对象文件与库链接起来以创建可执行文件或动态链接库文件的工具. link.exe的输入文件包括obj文件.lib文件. ...

  2. Steve Yegge:Google面试秘籍

    我憋了很长时间想写点关于去Google面试的秘籍.不过我总是推迟,因为写出来的东西会让你抓狂.很可能是这样.如果按统计规律来定义"你"的话,这文章很可能让你不爽. 为啥呢?因为啊- ...

  3. servlet 将输入内容通过拼接页面的方式显示出来

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  4. 动态规划之一最长上升子序列LIS

    //最长上升子序列 #include<iostream> #include<cstring> using namespace std; const int maxn = 101 ...

  5. Java--格式化输出

    Java的格式化输出等同于String.Format,与C有很大的相似,比如 System.out.printf("%8.2f", x); 在printf中,可以使用多个参数,例如 ...

  6. Qt 无边框窗体改变大小 完美实现

    近期,做项目用到无边框窗体,令人蛋疼的是无边框窗体大小的改变要像右边框那样,上下左右四周,而且要流畅. 网上也找了些代码,发现居然还要连接到windows事件,这显然不合常理,后来自己新建了demo, ...

  7. CloudStack全局配置參数

    參数 描写叙述 类型 默认值 account.cleanup.interval 清除用户账户所须要等待的时间(秒) 整数 86400 agent.lb.enabled If agent load ba ...

  8. linux head命令

    head 与 tail 就像它的名字一样的浅显易懂,它是用来显示开头或结尾某个数量的文字区块,head 用来显示档案的开头至标准输出中,而 tail 想当然尔就是看档案的结尾. 1.命令格式: hea ...

  9. C#面向对象1 类 以及 类的继承(new、ovverride)

    类 的典型代码============================== 包括 属性及其判断赋值  方法  构造函数及其重载 )                 {                  ...

  10. Java7新特性(一)Coin

    1.语法糖 数字下划线   2.switch语句中的String   3.multicatch   4.final重抛 对比上份代码   5.try-with-resources(TWR) AutoC ...