Managed String to unmanaged char*
-
Hallo zusammen,
ich hab leider noch ein Problem bei dem Versuch einer unmanaged DLL (C++) einen String zu übergeben, der dann richtig verarbeitet werden soll. Meine unmanaged DLL Funktion hat folgenden Funktionsrumpf:
DLLEXPORT_IMPORT int __stdcall EDM_RC_SetLocalDownloadPath(CAObjHandle hApp, char *sLocalDownloadPath) { int iret = 0; int ilength = 0; int iHandleIndex = 0; //Get_Handle_Index iretChk(EDM_RC_Get_Handle_Index(hApp, &iHandleIndex)); //some rough checks, e.g. when last "\\" is missing add it "c:\a" is minimum ilength = strlen(sLocalDownloadPath); if(ilength >=4) { strncpy(EDM_RC_Internal_data[iHandleIndex].sLocalDownloadPath, sLocalDownloadPath, EDM_RC_LOCAL_DOWNLOAD_PATH_LENGTH-1); EDM_RC_Internal_data[iHandleIndex].sLocalDownloadPath[EDM_RC_LOCAL_DOWNLOAD_PATH_LENGTH-2] = 0x0; ilength = strlen(EDM_RC_Internal_data[iHandleIndex].sLocalDownloadPath); if(EDM_RC_Internal_data[iHandleIndex].sLocalDownloadPath[ilength-1] != '\\') strcat(EDM_RC_Internal_data[iHandleIndex].sLocalDownloadPath, "\\"); iret = Create_Full_Dir_NT(EDM_RC_Internal_data[iHandleIndex].sLocalDownloadPath); } else iret = EDM_RC_ERROR_LOCAL_DOWNLOAD_PATH; Error: return(iret); }
Wie man erkennen kann, soll die Pfaddefinition, die mit "sLocalDownloadPath" rein kommt, in eine interne Struktur geschrieben werden. Leider komm ich schon garnicht so weit, weil mir die Überprüfung
ilength = strlen(sLocalDownloadPath);
einen Strich durch die Rechnung macht. Es wird nämlich nur der erste Buchstabe des Strings übergeben und nicht der komplette String. Ich kann im Debugger zwar mit
sLocalDownloadPath+1
sLocalDownloadPath+2
..
etc.auf die einzelnen char-Elemente zugreifen, jedoch will und soll ich nichts an der bestehenden unmanaged Funktion ändern. Gibt es eine Möglichkeit, dies zu realisieren? Ich hab in meinem C# Programm schon einige Konstellationen mit IntPtr, byte[], [MarshalAs], etc... probiert, aber bis jetzt hat es nicht geklappt. Wie kann ich auf C# Seite einen IntPtr übergeben, der nicht nur auf der erste Element zeigt, sondern den kompletten String der Funktion übergibt?
Hier noch mein C# Code:
[DllImport("EDM_RC.dll", EntryPoint = "EDM_RC_SetLocalDownloadPath", CallingConvention = CallingConvention.StdCall)] private static extern int edm_SetLocalDownloadPath(IntPtr hEDMHandle, IntPtr sDownloadPath); public bool SetLocalDownloadPath(string sLocalDownloadPath) { bool retVal = false; try { var ptr = Marshal.AllocHGlobal(260 * Marshal.SizeOf(typeof(char))); ptr = Marshal.StringToHGlobalUni(sLocalDownloadPath); if (m_iEDMHandle != IntPtr.Zero) { int val = edm_SetLocalDownloadPath(m_iEDMHandle, ptr); if (val == 0) { retVal = true; } else { retVal = false; } } } catch (System.Exception ex) { MessageBox.Show(ex.Message); return false; } finally { } return retVal; }
Ich wäre sehr froh, wenn mir einen einen guten Tipp geben könnte!
Vielen Dank
Gruß
-
Du übergibst einen UTF-16 String und probierst mit Funktionen, welche für ASCII gemacht wurden, mit dem String zu arbeiten. UTF-16 kann Nullbytes enthalten, daher funktioniert
strlen
nicht.Die Frage ist nun, was die unmanaged Funktion erwartet? Also welches Encoding wird dort erwartet? ASCII oder womöglich UTF-8? Oder ein Latin-1/2/3/etc? Dem entsprechend musst du den String vorher enkodieren, bevor du ihn an die Funktion übergibst. Je nach Enkodierung gibt es unterschiedliche Vorgehensweisen.
Grüssli