C#调用C++DLL时的编码转换-编码、字符集

2023-11-10

最近项目,需要在C# 中调用C++ 写的DLL,因为C# 默认的编码方式是Unicode,而调用的DLL规定只处理UTF8编码格式的字符串,DLL中的输入参数类型char*被我Marshal成byte[],输出参数类型char**被我Marshal成了string(C++和C#之间的类型转换请参阅相关资料),于是我就经历了无数次用于接收时的string-->string(UTF8-->Unicode)和用于发送时的string-->byte[](Unicode-->UTF8)这样频繁的编码转换,期间多次出现中文乱码,看来编码转换并非想象中那么简单,今天花时间google一番,原来以前的理解确实不够深,存在很多误区,现整理如下:

  (一)、Encoding和CharSet

  为什么先提这两个,实属问题之源。在C#中包装DLL的时候,DllImportAttribute当中的选项CharSet着实让我糊涂了很久,MSDN曰:规定封送字符串应使用何种字符集,其中枚举值有Ansi和Unicode,我真不知道到底改选哪一个。于是乎, google一番,Encoding这棵救命草被我找到,同时也释疑了不少疑惑。

  首先,字符集不同于编码,以前总将它们混为一谈,CharSet是字符集,Encoding是编码。字符集是字符的集合,规定这个集合里有哪些字符,每个字符都有一个整数编号(只是编号不是编码);而编码是用来规定字符编号如何与二进制交互,每个“字符”分别用一个字节还是多个字节存储。啊呜,原来这样,那我这里接触到的Ansi、Unicode、UTF8等等等等究竟是怎么回事呢,借此机会,一探究竟!^_^

  (二)、Ansi、Unicode、UTF8、bala bala

  提到字符集,有ASCII、GB2312、GBK、GB18030、BIG5、JIS等等多种,与此相对应的编码方式为ASCII、GB2312、GBK、GB18030、BIG5、JIS(囧,难怪糊涂如我般的人如此多),但是Unicode字符集却有多种编码方式:UTF-8、 UTF-7、UTF-16、 UnicodeLittle、UnicodeBig。原来如此,字符集与编码原来是这个样子。ˇˍˇ|||

  那Ansi又是什么呢?

  Ansi:系统编码的发展经历了三个阶段,ASCIIàAnsi(不同国家语言本地化)àUnicode(标准化),原来Ansi编码也好,Ansi字符集也好,都是指本地化的东西,在简体中文系统下,ANSI 编码代表 GB2312 编码,Windows下自带的记事本程序,默认的就是ANSI编码。呵呵,那偶就去试试吧,输入“anhui合肥”(不含引号),保存编码方式选“ANSI”,查看,哦,9个字节,明白了,原来Ansi编码保留了对ASCII编码的兼容,当遇到ASCII字符时,采用单字节存储,当遇到非ASCII编码时,采用双字节表示(GB2312编码)。

  (三)、DllImportAttribute中的CharSet枚举值选择

  对字符集和编码的概念清楚了以后,终于可以研究C#中调用非托管的DLL的方法咯。从托管应用程序去调用非托管代码,如果CharSet=Unicode,则DLL中的接口函数将出现的所有字符串(包括参数和返回值)视为Unicode字符集,Ansi一样的道理。真不错,了解到这里总算有点拨云见日的感觉了!O(∩_∩)O

  好像目前需要了解的知识点都差不多了,终于可以开始来解决我的问题了, (*^__^*)。回顾整理一下,第一:我需要调用非托管代码,第二:非托管代码只处理UTF8编码格式的字符,第三,万恶的中文乱码,接口函数签名中,无论参数还是返回值,接收到或是发送出的字符串都含有中文。呵呵,看来上面的知识应该可以解决这个问题了:首先接收字符串,因为接收到的是UTF8编码格式,CharSet属性肯定要设置成Unicode了,接收后要正确显示中文,在当前系统中,需要将编码方式转换成GB2312,即Encoding.Default;另外关于发送字符数组,因为无论是C#中默认的Unicode编码方式,还是DLL处理时规定的UTF8编码方式,都是Unicode字符集的一种编码方式,所以CharSet也要设置成Unicode,只是要在发送前需要将字符数组转换一下编码方式。以下附带两个简单的函数实现。

以下是代码片段:
    // 转换接收到的字符串 
  public string UTF8ToUnicode(string recvStr) 
  { 
  byte[] tempStr = Encoding.UTF8.GetBytes(recvNotify); 
  byte[] tempDef = Encoding.Convert(Encoding.UTF8, Encoding.Default, tempStr); 
  string msgBody = Encoding.Default.GetString(tempDef); 
  return msgBody; 
  } 
  // 转换要发送的字符数组 
  public byte[] UnicodeToUTF8(string sendStr) 
  { 
  string tempStr = Encoding.UTF8.GetString(sendStr); 
  byte[] msgBody = Encoding.UTF8.GetBytes(tempUTF8); 
  return msgBody; 
  }

  总结一下,本文因项目完成的需要,难免存在局限性,只讨论了两种情况:Unicode编码的字符串转UTF8格式的字符数组,以及UTF8格式的字符串转Unicode格式的字符串,上面两个方法均通过测试,至此总算解决了中文乱码的问题。平台调用的知识点很多,只有真正掌握必需的基础知识和平台调用的原理,才能做到活学活用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#调用C++DLL时的编码转换-编码、字符集 的相关文章

  • ASP.NET Web 应用程序中的身份验证遇到问题

    我正在尝试对从登录页面登录我的 Web 应用程序的用户进行身份验证 我正在使用本教程 http support microsoft com kb 301240作为指南 它几乎准确地解释了我希望做什么 但是当我输入用户名和密码时 验证不起作用
  • NDK 应用 onDestroy 清理 - 如何 DetachCurrentThread

    因此 如果我们连接 我们必须在完成后分离线程 对吗 JNIEnv get jni env JNIEnv res JAVA VM gt GetEnv void res JNI VERSION 1 6 Using cached JavaVM J
  • 将公历日期转换为儒略日期,然后再转换回来(随着时间)

    我正在编写一个程序 必须将当前的公历日期和时间转换为儒略日期 然后再转换回公历门 最终我需要添加能够添加年 月 日 小时 分钟和秒的功能 但我需要先解决这部分问题 现在我已经从公历日期转换为儒略日期 所以从逻辑上讲 我觉得我应该能够以某种方
  • 平滑手绘曲线

    我有一个允许用户绘制曲线的程序 但这些曲线看起来不太好 它们看起来摇摇欲坠 而且是手绘的 所以我想要一种能够自动平滑它们的算法 我知道平滑过程中存在固有的模糊性 因此它不会每次都完美 但这种算法似乎确实存在于多个绘图包中 并且它们工作得很好
  • 最新 .Net MongoDb.Driver 的连接问题

    我创建了一个 MongoLab 沙箱数据库 我与 MongoChef 连接 效果很好 我通过 Nuget 安装了 MongoDB Driver 2 2 2 我编写了一些简单的 C 演示代码 但就是无法使其工作 连接字符串是直接从 Mongo
  • 如何将字符串方法应用于数据帧的多列

    我有一个包含多个字符串列的数据框 我想使用对数据帧的多列上的系列有效的字符串方法 我希望这样的事情 df pd DataFrame A 123f 456f B 789f 901f df Out 15 A B 0 123f 789f 1 45
  • 如何从 Qt 应用程序通过 ODBC 连接到 MySQL 数据库?

    我有一个新安装的 MySQL 服务器 它监听 localhost 3306 从 Qt 应用程序连接到它的正确方法是什么 原来我需要将MySQL添加到ODBC数据源 我在遵循这个视频教程后做到了这一点 https youtu be K3GZi
  • 嵌入资源文件的路径

    我的资源文件中有一个图标 我想引用它 这是需要图标文件路径的代码 IWshRuntimeLibrary IWshShortcut MyShortcut MyShortcut IWshRuntimeLibrary IWshShortcut W
  • 如何在C中同时运行两个子进程?

    所以我开始学习并发编程 但由于某种原因我什至无法掌握基础知识 我有一个名为 fork c 的文件 其中包含一个 main 方法 在此方法中 我将 main 分叉两次 分别进入子进程 1 和 2 在孩子 1 中 我打印了字符 A 50 次 在
  • Monotouch全局异常处理

    我在野外发现了一只令人讨厌的虫子 但我无法确定它的具体情况 有没有办法拥有全局 Try Catch 块 或者有办法处理 Monotouch 中未处理的任何异常 我可以包起来吗UIApplication Main args 在 try cat
  • 如何将 Q 格式整数转换为浮点数(反之亦然)?

    我四处搜寻 找不到一个很好的问题来回答这个问题 给定一个整数 使用Q Format https en wikipedia org wiki Q number format 如何将该数字转换为普通浮点类型 反之亦然 如何将浮点类型转换为Q F
  • .NET 5 EF Core SaveChangesAsync 因错误而挂起

    尽管这个问题有很多结果 但没有一个真正给我明确的答案 每次我尝试通过 AddAsync 和 SaveChangesAsync 方法插入错误数据 例如重复的主键 时 我都会看到以下日志 执行 DbCommand 失败 15 毫秒 我还在 SQ
  • 调用异步方法在视图模型的构造函数中加载数据有警告

    我的视图包含一个 ListView 它显示来自互联网的一些数据 我创建一个异步方法来加载数据并在我的视图模型的构造函数中调用该方法 它有一个警告提示我现在使用await关键字 还有其他解决方案可以在构造函数中异步加载数据吗 有几种可以应用的
  • 我在使用 ado.net 时收到错误 Argument 2 may not be pass with ref keywords

    int t 0 cmd Parameters AddWithValue Res ref t 我在第二行收到错误 参数 2 不能与 ref 关键字一起传递 您只能通过引用传递参数ref if the 范围 is a ref参数也是如此 Add
  • 我可以将 UseCSharpNullComparisonBehavior 用于单个查询吗?

    我有一个查询 该查询曾经是存储过程 现已转换为 EF 查询 现在已经超时了 使用 SQL Profiler 我可以看到生成的 SQL 的唯一区别是 EF 转变的新行为entity Property value into entity Pro
  • 传递数组时在 C 中的函数参数中强制指定数组大小

    Context 在 C 中 我有一个以数组作为参数的函数 该参数用作该函数的输出 输出的大小始终相同 我会 让阅读代码的人清楚所需的大小 不过它已经在函数注释中了 理想情况下 编译会输出警告或错误 这样我就可以在编译时而不是运行时防止出现问
  • Type.GetInterfaces() 仅适用于声明的接口

    首先 像这样的问题有很多 也许有些OP甚至在问同样的问题 问题是这些问题的答案 无论是否接受 都没有真正回答这个问题 至少我找不到 如何确定类直接声明的接口 而不是由父级或声明的接口继承的接口 e g interface I interfa
  • 选择合适的IDE

    您会推荐使用以下哪种 IDE 语言来在 Windows 下开发涉及识别手势并与操作系统交互的项目 我将使用 OpenCV 库来执行图像处理任务 之后 我将使用 win32 API 或 NET 框架与操作系统交互 具体取决于您建议的工具 性能
  • 具有四个 && 的 LINQ Where 子句

    我正在尝试在Where 子句中创建一个带有4 个参数的LINQ 查询 这是一个 Windows 8 应用程序项目 我正在使用 SQLite 数据库 SQLite 实现 https github com praeclarum sqlite n
  • 为什么在构造函数中设置字段是(或不是)线程安全的?

    假设您有一个像这样的简单类 class MyClass private readonly int a private int b public MyClass int a int b this a a this b b public int

随机推荐

  • matlab常用分布极大似然估计函数用法(含例子实现)

    本博文源于matlab概率论运用 学过 概率论 的同学都知道 极大似然估计一般用于区间估计的 而matlab已经将其封装好由我们自己调用 参数估计的MATLAB函数 函数 功能 mu sigma muci sigmaci normfit x
  • 使用ScrollView实现下拉刷新(一)

    转载自 http blog csdn net a6920502 article details 8759244 使用ListView来做下拉刷新有很多例子 而且封装的很好 ListView有 header 但是如果不使用ListView的下
  • 使用C++完成以栈为基础的简易计算器,并使用Qt5制作可视化界面

    使用C 完成以栈为基础的简易计算器 并使用Qt5制作可视化界面 一 计算器内部逻辑构造 在完成计算器时选用栈数据结构 自己编写的和标准模板库中的都可 要求支持加减乘除和逻辑与或非运算 可计算整数和小数 这一部分有很多思路都可以实现 我的写法
  • C语言-操作环境变量

    20180216 c语言操作环境变量 使用C语言操作环境变量 获取环境变量内容 char getenv char name 参数 name欲获取的环境变量名称 返回值 环境变量值 NULL表示没有找到环境变量 设置环境变量 int pute
  • 【直播预告】Stable Diffusion篇

    08月23日 18 30 19 30 大淘宝技术与DataFun联合策划了本次活动 邀请阿里巴巴大淘宝技术应用开发工程师赤燕老师分享 Stable Diffusion WebUI 从零基础到入门 欢迎大家按时收看直播 赤燕 淘天集团 大淘宝
  • Windows系统打完补丁之后,CRM异步服务没了?

    此部署中缺少一个或多个服务器角色 昨天应公司安全部门要求要给windows系统打补丁 做安全测试 自从CRM安装之后 windows的补丁就没有安装过 就先拿测试环境试试 顺风顺水的打完补丁 登录CRM访问正常 登录服务器 服务都正常启动了
  • 【Linux】Linux8安装docker图文详细步骤以及常用指令

    Docker 是一个开源的应用容器引擎 让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中 然后发布到任何流行的Linux或Windows操作系统的机器上 也可以实现虚拟化 切换到源目录 备份原来的源 root localhost d
  • 【Unity实用小方法】鼠标双击的判断

    using UnityEngine using System Collections public class DoubleClick MonoBehaviour 计时器 在一定的时间内双击有效 private float time 0f
  • 耗时两周手撸了一个 RPC 轮子,是驴子是马拉出来遛遛

    手撸 RPC 轮子系列文章目录 从零开始造 RPC 轮子系列 01 我为什么要去造一个轮子 从零开始造 RPC 轮子系列 02 演示轮子 是驴是马拉出来遛遛 TODO 从零开始造 RPC 轮子系列 03 完事具备 只差一个环境搭建 TODO
  • 《软件测试》第二章 软件开发的过程

    软件测试 第二章 软件开发的过程 2 1 产品的组成部分 2 1 1 软件产品需要多少投入 2 1 2 软件产品由哪些部分组成 2 2 软件项目成员 2 3 软件开发生命周期模式 2 3 1 大爆炸模式 2 3 2 边写边改模式 2 3 3
  • 使用自定义过滤器-Filter--实现对权限的控制

    提示 大牛大佬们就没必要垂阅了 如果很幸运的被大佬翻牌了 也希望能够给出指教 3Q 关于权限控制即包含功能权限 数据权限 我们使用的方式可谓多种多样 通过自定义注解编写AOP方式或是使用第三方提供好的框架如 shiro 或 springse
  • 计算机cpu针脚,cpu针脚弯了怎么办 cpu针脚弯了解决方法【详解】

    经常使用电脑我们就应该掌握一些方法技巧 那有时候我们经常会听说cpu针脚弯了大家怎么识别是不是弯了 最有效的办法是看主板CPU 插座 正规厂家都会有标识 我们可以认识的去看说明 那大家知道cpu针脚弯了我们应该怎么去处理呢 下面小编就给大家
  • 使用 mysql-5.7.35-1.el7.x86_64.rpm-bundle.tar在阿里云服务器使用CentOS 7进行安装

    使用wget https downloads mysql com archives get p 23 file mysql 5 7 35 1 el7 x86 64 rpm bundle tar下载所需的安装包 使用tar xvf mysql
  • 有关时间的相关方法(时间格式化、日期差等)

    时间格式化 将时间转化为 年 月 日 function dateFormatConversion inputTime var date new Date inputTime var y date getFullYear var m date
  • 计算机视觉学生论文,计算机视觉方面论文参考文献

    计算机视觉方面论文参考文献 发布日期 2020 12 30 所属栏目 论文发表指导 计算机视觉是一门研究如何使机器 看 的科学 更进一步的说 就是是指用摄影机和电脑代替人眼对目标进行识别 跟踪和测量等机器视觉 并进一步做图形处理 使电脑处理
  • TXRX串口通信RAM版自己编译

    引言 目前 javaxcomm 旧 gunio 新 目前rxtx 2 1 7 bins r2 zip版本为32位的win或者x86或者x386 mfz rxtx 2 2 32位 64位 rar有64位 但是不支持ARM架构的 下载sourc
  • 计算机基础操作

    1 计算机软件 计算机软件可以使计算机按照事先预定好的顺序完成特定的功能 计算机软件按照其功能划分为系统软件与应用软件 系统软件 DOC Disk Operating System Windows Linux Unix Mac Androi
  • Android 网络地址之实现检查主机名的功能

    博主前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住也分享一下给大家 点击跳转到网站 效果演示 实现步骤 一 布局页面activity inet address xml
  • pinia的storeToRefs和普通的toRefs有啥区别

    在 Vue 3 中 pinia 是一个基于 Vue 3 的状态管理库 Pinia提供了一种类似于Vuex的方式来管理全局状态 它提供了 storeToRefs 和 toRefs 这两个函数 用于处理状态的转换 其中 storeToRefs
  • C#调用C++DLL时的编码转换-编码、字符集

    最近项目 需要在C 中调用C 写的DLL 因为C 默认的编码方式是Unicode 而调用的DLL规定只处理UTF8编码格式的字符串 DLL中的输入参数类型char 被我Marshal成byte 输出参数类型char 被我Marshal成了s