c#调用dll接口传递utf-8字串方法

1. 起

VCU10之视频下载模块,采用纯python实现,c++代码调用pythonrun.h配置python运行环境启动python模块,以使界面UI能够使用其中功能。

棘手问题!用去一天时间反复打印日志,验证所传字串区别,以期望发现问题定位问题,直至下班前始有灵感。

验证发现,非中文字符可以正常下载,中文字符下载解析失败,当时即想到可能是字串不统一所致,就在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模块,则打印日志为:

dir: d:\kvd新, code: ‘d:\\kvd\xd0\xc2‘

而直接运行python代码,其输出却是:

dir: d:\kvd新, code: ‘d:\\kvd\xe6\x96\xb0‘

用c#建Demo验知\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 -1;
        }

        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 + 1);
            Marshal.Copy(utf8bytes, 0, ptr, utf8bytes.Length);
            Marshal.WriteByte(ptr, utf8bytes.Length, 0);
            return ptr;
        }

        public object MarshalNativeToManaged(IntPtr pNativeData)
        {
            if (pNativeData == IntPtr.Zero)
                return null;

            List<byte> bytes = new List<byte>();
            for (int offset = 0; ; offset++)
            {
                byte b = Marshal.ReadByte(pNativeData, offset);
                if (b == 0) break;
                else bytes.Add(b);
            }
            return Encoding.UTF8.GetString(bytes.ToArray(), 0, 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!运行效果如下:

至此,一个技术难点解决,记录于此。

时间: 2024-08-02 11:00:31

c#调用dll接口传递utf-8字串方法的相关文章

一、单页应用如何调用微信接口和手机端的一些方法?

因为angular 是单页应用,所以在调用一些手机端可微信接口的地方会很麻烦,这里总结一下在手机端调用分享和调用微信接口的时候出现的问题及解决的办法: 出现问题: 手机端的方法如果有回调,H5需要调用手机端某个方法的回调时,不管在哪个页面需要回调该方法都无法回调成功 如果做有关微信公众平台接口,在任何页面也是无法调用该接口 解决办法: 出现这种问题的原因是由于angular是单页应用引起的 解决方案:目前只想到一种解决办法就是:在index.html页面申明一个全局变量,然后将手机端或者微信接口

C#调用C接口字符参数编码的问题解决方法

1.传入单字节ANSI字符 [DllImport("hostIO", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int initHost([MarshalAs(UnmanagedType.LPStr)] string host); 2.传入双字节Unicode字符 [DllImport("hostIO", CharSet = C

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

摘 要:在<csdn开发高手>2004年第03期中的<化功大法——将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资源中释放出来,通过静态加载延迟实现DLL函数的动态加载,程序退出后实现临时文件的自动删除,从而为解决“DLL Hell”提供了一种解决方案.这是一个很好的设计思想,而且该作者也用C++实现了,在Internet上也有相似的VB程序,但在某一技术论坛上提起这种设计方法时,有网友提出:“这种方法好是好,但就是启动

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

原文:C#程序实现动态调用DLL的研究 摘  要:在<csdn开发高手>2004年第03期中的<化功大法--将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资源中释放出来,通过静态加载延迟实现DLL函数的动态加载,程序退出后实现临时文件的自动删除,从而为解决"DLL Hell"提供了一种解决方案.这是一个很好的设计思想,而且该作者也用C++实现了,在Internet上也有相似的VB程序,但在某一技术论坛

DLL接口自动化测试总结

1. DLL接口测试方法介绍 在最近测试的项目中,系统给业务端提供DLL文件,业务端通过DLL文件中的C++接口实现系统功能,这就需要对DLL中的C++接口进行详细功能测试. 本文主要介绍项目测试中使用的DLL接口测试方法及基于AutoIT实现的DLL接口自动化测试方法. 1.1 VS2005 通过VS2005可以直接加载DLL文件中的C++接口,模拟业务端调用,传递一些参数值从而验证接口返回码等功能是否正确接口.这部分代码,类似与白盒测试中编写的驱动模块,需要有一定的C++编程基础. 项目初期

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

摘   要: 在< csdn 开发高手> 2004 年第 03 期中的<化功大法——将 DLL 嵌入 EXE >一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资源中释放出来,通过静态加载延迟实现DLL函数的动态加载,程序退出后实现临时文件的自动删除,从而为解决“ DLL Hell ”提供了一种解决方案.这是一个很好的设计思想,而且该作者也用 C++ 实现了,在 Internet 上也有相似的 VB 程序,但在某一技术论坛上提起这种设计方法时

android调用webservice接口获取信息

我的有一篇博客上讲了如何基于CXF搭建webservice,service层的接口会被部署到tomcat上,这一篇我就讲一下如何在安卓中调用这些接口传递参数. 1.在lib中放入ksoap2的jar包并导入 2.在xml 配置文件中加入: <!-- 访问网络的权限 --> <uses-permission android:name="android.permission.INTERNET" /> 3.接下来就要通过代码调用借口了 String WSDL_URI

C# 调用Java接口

最近工作任务中包含了系统之间数据的互通,当然就考虑系统互相开通接口来实现通信了! 作为.NET的开发者,还没有调用过Java接口的经历,惭愧惭愧! 话不多说,直接进入正题! 调用webservice接口,.NET最快的方法是什么? 1,当然是添加服务引用了! 填上WSDL地址,代码中new一个xxxxClient对象,找到方法,传入参数,得到结果,very easy! 2,用SvcUtil生成代理类,在Visual Studio工具中找到它! 什么?你找不到?那你去别处找找如何添加它吧,嘿嘿!

windows下,python调用dll例子,展示如何传递字节码流参数到dll接口

工作上需要用python调用dll解析码流输出到文件,如何调用dll很多博客都有描述,请参考如下blog: 如何调用请参考: http://blog.csdn.net/lf8289/article/details/2322550 WinDLL和CDLL的选择,请参考: http://blog.csdn.net/jiangxuchen/article/details/8741613 传递自定义的结构,请参考: http://www.jb51.net/article/52513.htm 但是如何将一