C # Call the dll interface to pass the UTF-8 string method,
1. StartSource:
The video download module of VCU10 is implemented by pure python encoding, and the c ++ code calls pythonrun. h. Configure the python runtime environment to start the python module and compile it as a dll to call c # so that the UI can use the functions in the interface.
Do not ask why IronPython is not used. It is not an orthodox Python and the download module should also be used by Mac products.
Tricky problem! Print logs repeatedly in one day to verify the differences between the passed strings, so that you can locate the problem until you get off work.
Verification found that non-Chinese characters can be downloaded normally, and Chinese characters cannot be downloaded and parsed. At that time, it was possible that the strings were not uniform, and the python code tried to convert the strings.
The original interface encapsulation code is as follows:
[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);
For example, if savePath is set to [d: \ vcu new], the dll calls the python module and prints its encoding information:
print 'dir: ' + dir + ', code: ' + repr(dir))
The log is printed as follows:
Dir: d: \ kvd new, code: 'd: \ kvd \ xd0 \ xc2'
The output of directly running python code is:
Dir: d: \ kvd new, code: 'd: \ kvd \ xe6 \ x96 \ xb0'
Use c # To create a Demo and use Encoding to parse the gb2312 Encoding of the word \ xd0 \ xc2 for [new] And the UTF-8 Encoding of \ xe6 \ x96 \ xb0 for [new] characters.
2. String Encoding
The default c # encoding in Win7 64-bit Simplified Chinese version:
By doing this simple verification, we found that the default encoding is gb2312. The python code used uses UTF-8 encoding to take into account Chinese characters and other multi-byte characters.
The problem is that the dll Interface string transmission mode needs to be changed to the UTF-8 string for transmission, but the c # built-in does not have the UTF-8 package, so you can customize it.
3. UTF8Marshaler
// The interface data is set to public class UTF8Marshaler: ICustomMarshaler {public void CleanUpManagedData (object managedObj) {} public void CleanUpNativeData (IntPtr pNativeData) {Marshal. freeHGlobal (pNativeData);} public int GetNativeDataSize () {return-1;} public IntPtr implements almanagedtonative (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 = Marshal. allocHGlobal (utf8bytes. length + 1); Marshal. copy (utf8bytes, 0, ptr, utf8bytes. length); Marshal. writeByte (ptr, utf8bytes. length, 0); return ptr;} public object implements alnativetomanaged (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 utf8internaler instance = new utf8internaler (); public static icustominternaler GetInstance (string cookie) {return instance ;}}
4. Update the interface string sending Style
[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);
Verification work OK! The running effect is as follows:
So far, a technical difficulty is recorded here.