C # неуправляемые вызовы функций, возможная потеря данных, Ascii Vs.Юникод, китайские имена папок - PullRequest
1 голос
/ 17 сентября 2011

Итак, вот в чем дело, я работаю на C # -приложении, которое вызывает унаследованную C ++ dll, которая, в свою очередь, перебирает каталог, извлекая имена определенных каталогов, то есть каталогов, в которых есть .lib, у меня есть каталог с следующие 3 папки: Default.Lib, 中文 文本 帧 的 文件 .lib, 我们 的 .lib.

Как вы можете видеть, у нас есть несколько китайских имен папок, строка встроена в память с помощью кода c ++, как вы можете видеть ниже, она использует strcat для построения ее в памяти. однако, когда управление возвращается обратно к коду c #, кажется, что часть этих данных потеряна, и только две оставшиеся папки - это первые две. Default.Lib, 中文 文本 帧 的 文件 .lib, что-то с 我们 的 .lib теряется в переводе, я был бы очень признателен за любые идеи, которые кто-либо может иметь. спасибо.

Фрагмент кода C #

 lock (padLock)
            {
                ConnectSign(service);

                int size = MaxFileListSize * 100;
                byte[] mem = new byte[size];
                string finalList;
                int used = size;
                int fileCount = 0;
                string library = "*";
                string extension = "*";
                V7_FILE_LIST_TYPE type = V7_FILE_LIST_TYPE.LibraryList;

                fixed (byte* listbytes = mem)
                {
                    int error = NativeMethods.GetFileDirInfo(sign, type, fileServer, library, extension, &fileCount, listbytes, &used);
                    if (error != 0)
                        throw new V7ResponseException(error, sign, service, "GetFileDirInfo");
                }

                finalList = Encoding.Default.GetString(mem, 0, (int)used);

                string[] libraryArray = finalList.Split(new char[] { '\n', '\0' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < libraryArray.Length; i++)
                {
                    int index = libraryArray[i].LastIndexOf(".lib", StringComparison.OrdinalIgnoreCase);
                    if (index > 0)
                        libraryArray[i] = libraryArray[i].Substring(0, index);
                    //libraryArray[i] = libraryArray[i].Trim().ToLower(CultureInfo.CurrentCulture).Replace(".lib", string.Empty);
                }

                return libraryArray;
            }

[DllImport("V7SSRpc.dll", CharSet = CharSet.Ansi, EntryPoint = "V7ssGetFileDirInfo", BestFitMapping = false, ThrowOnUnmappableChar = true)]
            public static extern int GetFileDirInfo(string sign, V7_FILE_LIST_TYPE type, string fileServer, string library, string extension, int* fileCount, byte* files, int* bytesUsed);

enter image description here ***************************** C ++ DLL code ------------------ --------------------

   //--------------------------------------------------------------------
    // RETURN :
    //
    // PARAMS : eListType
    //              szServer
    //              szLib
    //              szExt
    //              *pdwFileCnt
    //              *pbyFileBuf
    //              *pdwFileBufSize
    //
    // REMARKS:
    //
    BOOL CVSign::apiGetFileDirInfo(V7_FILE_LIST_TYPE eListType, LPCSTR szServer, LPCSTR szLib, LPCSTR szExt, 
                                             DWORD *pdwFileCnt, char *pbyFileBuf, DWORD *pdwFileBufSize) const
    {
        BOOL bReturn=TRUE;
        CString sServer(szServer);
        CString sLib(szLib);
        CString sExt(szExt);
        CString sFileInfo, sTemp;
        CStringArray asFiles;
        CFileStatus status;
        CV7Files V7Files;
        DWORD dwBufUsed=0;

    // SOME OTHER LOGIC (not posted)

        USES_CONVERSION;

        //CoInitialize(NULL);
        //AVIFileInit();

        CString sFilePath;
        CV7SequenceFile V7Seq;

        CV7FileInfo fileInfo;

        // go through list of files and build the buffer with file names and other info
        for (nFile=0; nFile<nFiles; nFile++)
        {
            // MORE OBSCURED LOGIC

            sFileInfo += _T("\n");

            // add file info to buffer
            int nLen = sFileInfo.GetLength();
            if (dwBufUsed+nLen<*pdwFileBufSize)
            {
                strcat(pbyFileBuf, T2CA(sFileInfo)); //<--- THIS IS THE IMPORTANT PART
                int nTemp = sFileInfo.GetLength();
                dwBufUsed += nTemp;
            }
            else
            {
                *pdwFileBufSize = 0;

                AVIFileExit();
                CoUninitialize();

                return FALSE;
            }
        }   // end for files

        //AVIFileExit();
        //CoUninitialize();

        *pdwFileBufSize = dwBufUsed;

        return bReturn;
    } // end apiGetFileDirInfo()

enter image description here

1 Ответ

0 голосов
/ 17 сентября 2011

Я подозреваю, что проблема заключается в том, что вы указываете Charset=CharSet.Ansi, поэтому поведение маршалинга по умолчанию заключается в преобразовании возвращаемой строки в ANSI.Это вызовет проблему.

Возможно, вы захотите указать строку Charset=CharSet.Unicode и, возможно, указать пользовательский маршалинг для некоторых строк.См. http://msdn.microsoft.com/en-us/library/s9ts558h.aspx#cpcondefaultmarshalingforstringsanchor5 для получения информации о том, как изменить поведение маршалинга строки для отдельных параметров.

...