c#调用dll接口传递utf-8字串方法
1. 起源:
VCU10之视频下载模块,采用纯python编码实现,c++代码调用pythonrun.h配置python运行环境启动python模块,编译为dll给c#调用,以使界面UI能够使用其中功能。
不要问为什么不用IronPython,它不是正统Python,且下载模块亦要为Mac产品所用。
棘手问题!用去一天时间反复打印日志,验证所传字串区别,以期望发现问题定位问题,直至下班前始有灵感。
验证发现,非中文字符可以正常下载,中文字符下载解析失败,当时即想到可能是字串不统一所致,就在python代码试遍字串编码转换,均不奏效。
原接口封装代码如下:
[DllImport("VideoDownloader", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private extern static bool VDDownload(IntPtr instance, string savePath, string imageSavePath,
string quality, string ext, string subtitleLang);
比如传savePath为[d:\vcu新],dll调用python模块,打印其编码信息:
print 'dir: ' + dir + ', code: ' + repr(dir))
则打印日志为:
dir: d:\kvd新, code: 'd:\\kvd\xd0\xc2'
而直接运行python代码,其输出却是:
dir: d:\kvd新, code: 'd:\\kvd\xe6\x96\xb0'
用c#建Demo用Encoding反解析验知\xd0\xc2为[新]字的gb2312编码,\xe6\x96\xb0为[新]字的utf-8编码。
2、字串编码
Win7 64位简体中文版中c#的默认编码:

做如此简单验证,发现其默认编码为gb2312;而所用python代码,为兼顾中文等多字节字符,默认采用utf-8编码。
问题大抵就在这里了,dll接口字串传递方式,需改为utf-8字串进行传递,但c#内置没有utf-8封装器,自定义实现它。
3、UTF8Marshaler
//接口数据为utf-8编码所设置
public class UTF8Marshaler : ICustomMarshaler
{
public void CleanUpManagedData(object managedObj)
{
} public void CleanUpNativeData(IntPtr pNativeData)
{
Marshal.FreeHGlobal(pNativeData);
} public int GetNativeDataSize()
{
return -;
} 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 + );
Marshal.Copy(utf8bytes, , ptr, utf8bytes.Length);
Marshal.WriteByte(ptr, utf8bytes.Length, );
return ptr;
} public object MarshalNativeToManaged(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero)
return null; List<byte> bytes = new List<byte>();
for (int offset = ; ; offset++)
{
byte b = Marshal.ReadByte(pNativeData, offset);
if (b == )
break;
else
bytes.Add(b);
}
return Encoding.UTF8.GetString(bytes.ToArray(), , bytes.Count);
} private static UTF8Marshaler instance = new UTF8Marshaler();
public static ICustomMarshaler GetInstance(string cookie)
{
return instance;
}
}
4、更新接口字串封送样式
[DllImport("VideoDownloader", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private extern static bool VDDownload(IntPtr instance,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]
string savePath,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]
string imageSavePath,
string quality, string ext, string subtitleLang);
验证工作OK!运行效果如下:

至此,一个技术难点解决,记录于此。
c#调用dll接口传递utf-8字串方法的更多相关文章
- C#程序实现动态调用DLL的研究(转)
摘 要:在<csdn开发高手>2004年第03期中的<化功大法——将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资 ...
- C#程序实现动态调用DLL的研究[转]
摘 要: 在< csdn 开发高手> 2004 年第 03 期中的<化功大法——将 DLL 嵌入 EXE >一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在 ...
- C#程序实现动态调用DLL的研究
摘 要:在<csdn开发高手>2004年第03期中的<化功大法——将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资 ...
- DLL接口自动化测试总结
1. DLL接口测试方法介绍 在最近测试的项目中,系统给业务端提供DLL文件,业务端通过DLL文件中的C++接口实现系统功能,这就需要对DLL中的C++接口进行详细功能测试. 本文主要介绍项目测试中使 ...
- 转【C#调用DLL的几种方法,包括C#调用C\C++\C#DLL】
C#中dll调用方法 一. DLL与应用程序 动态链接库(也称为DLL,即为“Dynamic Link Library”的缩写)是Microsoft Windows最重要的组成要素之一, ...
- 【转】C#调用DLL
C#中如何调用动态链接库DLL(转) 每种编程语言调用DLL的方法都不尽相同,在此只对用C#调用DLL的方法进行介绍.首先,您需要了解什么是托管,什么是非托管.一般可以认为:非托管代码主要是基 ...
- android调用webservice接口获取信息
我的有一篇博客上讲了如何基于CXF搭建webservice,service层的接口会被部署到tomcat上,这一篇我就讲一下如何在安卓中调用这些接口传递参数. 1.在lib中放入ksoap2的jar包 ...
- python 调用RESTFul接口
本周需要将爬虫爬下来的数据入库,因为之前已经写好PHP的接口的,可以直接通过python调用PHP接口来实现,所以把方法总结一下. //python编码问题,因为好久用,所以很容易出现 # -*- c ...
- thinkjs学习-this.assign传递数据和ajax调用后台接口
在页面加载时,就需要显示在页面上的数据,可以在后台使用this.assign赋值,在前台通过ejs等模板获取:用户点击按钮,或者触发某些事件和后台进行交互时,就需要用到ajax调用后台接口.本文通过一 ...
随机推荐
- ABAP-语法检查
1.界面 2.代码 *&---------------------------------------------------------------------* *& Report ...
- RACSignal常见用法
RACSignal 两种用法, 1:异步操作,一般创建signal的时候写逻辑,然后通过subscribeNext拿到异步执行的结果 2:监听的属性的变化,及时给出回应,一般赋值的时候用RACObse ...
- 笔记本移动位置,切换网络ip后,虚拟机的mac系统无法联网解决
1.手动配置新的ip
- Visual SVN Server备份脚本
set tt=%date:~0,4%%date:~5,2%%date:~8,2% mkdir D:\SVN_BACKUP_%tt%\Repositories xcopy C:\Repositories ...
- 367. Valid Perfect Square
原题: 367. Valid Perfect Square 读题: 求一个整数是否为完全平方数,如1,4,9,16,……就是完全平方数,这题主要是运算效率问题 求解方法1:812ms class So ...
- Python读取图片尺寸、图片格式
Python读取图片尺寸.图片格式 需要用到PIL模块,使用pip安装Pillow.Pillow是从PIL fork过来的Python 图片库. from PIL import Image im = ...
- 20.struts2的数据填充和类型转换.md
目录 1. struts2的自动填充 2. struts2的对象填充 3. struts2的类型转换器 3.1 类继承关系 3.2 局部转换器 3.3 全局转换器 3.4 注意 1. struts2的 ...
- 25. IO流.md
目录 IO分类: 1.FIle类 1.1目录分隔符 1.2常用方法 2.FileInputStream类 2.1读取文件 3.FileOutputStream类 拷贝文件 4.缓冲流 4.1 Buff ...
- GIS案例学习笔记-CAD数据分层导入现有模板实例教程
GIS案例学习笔记-CAD数据分层导入现有模板实例教程 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 1. 原始数据: CAD数据 目标模板 2. 任务:分5个图层 ...
- SqlServer数据库碎片整理——BCC SHOWCONTIG
SQLServer提供了一个数据库命令——DBCC SHOWCONTIG——来确定一个指定的表或索引是否有碎片. 示例: DBCC SHOWCONTIG语法: 显示指定的表的数据和索引的碎片信息. ...