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字串方法的更多相关文章

  1. C#程序实现动态调用DLL的研究(转)

    摘 要:在<csdn开发高手>2004年第03期中的<化功大法——将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资 ...

  2. C#程序实现动态调用DLL的研究[转]

    摘   要: 在< csdn 开发高手> 2004 年第 03 期中的<化功大法——将 DLL 嵌入 EXE >一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在 ...

  3. C#程序实现动态调用DLL的研究

    摘 要:在<csdn开发高手>2004年第03期中的<化功大法——将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资 ...

  4. DLL接口自动化测试总结

    1. DLL接口测试方法介绍 在最近测试的项目中,系统给业务端提供DLL文件,业务端通过DLL文件中的C++接口实现系统功能,这就需要对DLL中的C++接口进行详细功能测试. 本文主要介绍项目测试中使 ...

  5. 转【C#调用DLL的几种方法,包括C#调用C\C++\C#DLL】

    C#中dll调用方法   一.      DLL与应用程序 动态链接库(也称为DLL,即为“Dynamic Link Library”的缩写)是Microsoft Windows最重要的组成要素之一, ...

  6. 【转】C#调用DLL

    C#中如何调用动态链接库DLL(转)     每种编程语言调用DLL的方法都不尽相同,在此只对用C#调用DLL的方法进行介绍.首先,您需要了解什么是托管,什么是非托管.一般可以认为:非托管代码主要是基 ...

  7. android调用webservice接口获取信息

    我的有一篇博客上讲了如何基于CXF搭建webservice,service层的接口会被部署到tomcat上,这一篇我就讲一下如何在安卓中调用这些接口传递参数. 1.在lib中放入ksoap2的jar包 ...

  8. python 调用RESTFul接口

    本周需要将爬虫爬下来的数据入库,因为之前已经写好PHP的接口的,可以直接通过python调用PHP接口来实现,所以把方法总结一下. //python编码问题,因为好久用,所以很容易出现 # -*- c ...

  9. thinkjs学习-this.assign传递数据和ajax调用后台接口

    在页面加载时,就需要显示在页面上的数据,可以在后台使用this.assign赋值,在前台通过ejs等模板获取:用户点击按钮,或者触发某些事件和后台进行交互时,就需要用到ajax调用后台接口.本文通过一 ...

随机推荐

  1. 【技术文档】jeecg3.7.3-maven搭建环境入门

    JEECG 微云快速开发平台(3.7.3)Eclipse-Maven版本手把手入门手册 官方标准开发工具:1. IDE        Eclipse Java EE IDE for Web Devel ...

  2. Java面试题_简答题

    作为一个大三在校生,很快就要去实习了,但总感觉自己连一个刚入门的菜鸟都不如,哎.发现自己连那个程序员的门槛都还没进,有点小伤心,不过伤心没用,努力向前才是我们现在应该做的事情. 下面是我之前在学校所从 ...

  3. nginx+php 开启https

    nginx 配置如下,配置好重启nginx,不是nginx -s reload,如果还不能访问肯定就是防火墙问题,关闭防火墙再试试. 我遇到的问题是:我服务器是ecs,域名解析到阿里云复杂均衡的,结果 ...

  4. Jquery select chosen 插件注意点

    <select style="width:200px;" name="carId" data-placeholder="选择车辆牌照" ...

  5. [jQ/PHP]再谈使用JS数组储值的运用(提交PHP处理)

    --------------------------------------------------------------------------------------------------- ...

  6. 简单实现"回车!=提交"(去除表单的回车即提交)

    -------------------------------------------------------------------------------------------------- 实 ...

  7. rhel7磁盘管理

     一.MBR主引导记录        MBR有512个字节,分为三个部分:第一部分446个字节,存储了引导分区:第二部分64字节为分区表:第三部分2个字节结束符:每个分区需16个字节,所以MBR的模式 ...

  8. Jumpserver 文档

    http://docs.jumpserver.org/zh/docs/admin_guide.html

  9. 2018面向对象程序设计(Java)第12周学习指导及要求

    2018面向对象程序设计(Java)第12周学习指导及要求 (2018.11.15-2018.11.18)   学习目标 (1) 掌握Java GUI中框架创建及属性设置中常用类的API: (2) 掌 ...

  10. 新手必看ES6基础

    ES6 基础 一.新的变量声明方式 let/const 与var不同,新的变量声明方式带来了一些不一样的特性,其中最重要的两个特性就是提供了块级作用域与不再具备变量提升. 通过2个简单的例子来说明这两 ...