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ß


  • Administrator

    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


Anmelden zum Antworten