String* in LPCTSTR konvertieren



  • Für die folgende Funktion muss ich die Serveradresse (smtp) als LPCTSTR übergeben, diese liegt jedoch als String* vor. Wie wandel ich also den String um??

    CSMTPConnection smtpConnection;
    String* smtp="BLABLA"
    smtpConnection.Connect(smtp);
    

    Immer eine nervige Angelegenheit mit diesen Typumwandlungen. 😞



  • Nimm die Struktur "StringConvA" und "StringConv" und das Define "StringConvT" in eine eigene H-Datei und dann kannst Du es ganz simpl überall verwenden.

    #include <windows.h> 
    #include <tchar.h> 
    #include <string> 
    using namespace System; 
    struct StringConvA 
    { 
      char *szAnsi; 
      StringConvA(System::String ^s) 
        : szAnsi(static_cast<char*>(System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(s).ToPointer())) 
      {} 
      ~StringConvA() 
      { 
        System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr(szAnsi)); 
      } 
      operator LPCSTR() const 
      { 
        return szAnsi; 
      } 
    }; 
    
    struct StringConvW 
    { 
      wchar_t *szUnicode; 
      StringConvW(System::String^ s) 
        : szUnicode(static_cast<wchar_t*>(System::Runtime::InteropServices::Marshal::StringToHGlobalUni(s).ToPointer())) 
      {} 
      ~StringConvW() 
      { 
        System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr(szUnicode)); 
      } 
      operator LPCWSTR() const 
      { 
        return szUnicode; 
      } 
    }; 
    
    #ifdef _UNICODE 
    #define StringConvT StringConvW 
    #else 
    #define StringConvT StringConvA 
    #endif 
    
    int _tmain() 
    { 
      String ^s = "abc"; 
      std::string ansi = StringConvA(s); 
      std::wstring unicode = StringConvW(s); 
      _tprintf(_T("%s"), (LPCTSTR) StringConvT(s)); 
    }
    


  • Erstmal Danke für die schnelle Hilfe.

    Die Sache war mir ein wenig zu aufwändig.

    Ich habe jetzt folgendes gemacht:

    CString smtpServer=configGetValue("smtpserver");
    CSMTPConnection smtpConnection;
    smtpConnection.Connect(smtpServer);
    

    Warum das jetzt funktioniert - keine Ahnung!? 😕

    Diese verschiedenen String-Typen werde ich wohl Zeit meines Lebens nie durchschauen.



  • Wahrscheinlich liegt das am Marshalling in .NET. Der Standard-Marshalling-Typ für "String" ist nämlich "LPCTSTR" bei Win32-Aufrufen.



  • Nein, CString hat eine automatische Konvertierung nach System::String...



  • Jochen Kalmbach schrieb:

    Nein, CString hat eine automatische Konvertierung nach System::String...

    Ich hab nur "String" gelesen und war vom ".NET-String" ausgegangen. Und da bin ich eigentlich felsenfest überzeugt, daß er nach "LPCTSTR" gemarshalled wird.

    Wenn ich auch damit falsch liege, bitte kurze Rückmeldung.



  • Sid2K6 schrieb:

    Ich hab nur "String" gelesen und war vom ".NET-String" ausgegangen. Und da bin ich eigentlich felsenfest überzeugt, daß er nach "LPCTSTR" gemarshalled wird.

    Ein .NET-String wird in C++/CLI gar nicht gemarschallt; zumindest nicht ohne weiteres. Er wird nur durch ein DllImport explizit gemarschallt...



  • Jochen Kalmbach schrieb:

    Sid2K6 schrieb:

    Ich hab nur "String" gelesen und war vom ".NET-String" ausgegangen. Und da bin ich eigentlich felsenfest überzeugt, daß er nach "LPCTSTR" gemarshalled wird.

    Ein .NET-String wird in C++/CLI gar nicht gemarschallt; zumindest nicht ohne weiteres. Er wird nur durch ein DllImport explizit gemarschallt...

    Jau. Ich weiss jetzt, wo das Problem liegt: Ich bin nämlich auch von einem DllImport ausgegangen, beispielsweise um einen Win32-Api-Aufruf aus .NET durchzuführen. Ich weiß aber nicht mehr, warum ich diese Idee im Kopf hatte.

    Du hast natürlich recht, ich bin irgendwo vollkommen falsch abgebogen. Muss das Wetter sein.



  • Danke für diesen Beitrag.
    Mir hat das sehr geholfen. Ich verwende die Visual Express C++ 2008 und da gibts offenbar kein "CString". Die "StringConv..."-Möglichkeit ermöglicht es mir mit "Path::GetFullPath(FileName);" den Pfad von "FileName" zu ermitteln und dann doch mittels "GetPrivateProfileString" (usw.) die INI-Einlesung vorzunehmen.
    Jetzt fange ich auch mit der Unsitte der Code-Schnippsel an, also hier (ein Teil) meiner Lösung:

    String^ FileName = "TestFiles_2.ini";
    PathAndName1 = Path::GetFullPath(FileName);
    GetPrivateProfileString(TEXT("files"),TEXT("Pfad"),TEXT("C:\\KeineAhnung"),Pfad,destSize,_T((LPCTSTR) StringConvT(PathAndName1)));
    std::cout << "Pfad = " << Pfad << "\n";

    Ubrigens geht das Ganze auch ohne "_T" (ausprobiert).

    -----------------------------------------------------------------------

    Nochwas allgemeines:
    Warum "Unsitte"? Einfach darum, weil man mit dem Schnippsel alleine manchmal gar nichts anfangen kann 😡 . Auch in der VE-Hilfe oder der MSDN-Lib werden oft nur die "Schnippsel" angegeben. Hier fehlen oft elementar wichtige Hinweise wie die "#includes" und auch welche Version von "Visual" (Express oder echtes Studio) man verwendet - manchmal noch mehr - und die muss man sich dann mühsam im Internet zusammenklamüsern. Aber in dem Fall oben habe ich keine anderen Includes verwendet als der sehr hilfreiche Jochen Kalmbach.

    Wenn ich nicht von der Firma aus gezwungen wäre meine Programme in C++ zu schreiben, dann würde ich das Ganze ja mit dem "bösen" VB schreiben. Ich weis zwar nicht ob VB auch zwischen LPCSTR und String unterscheidet und man da "geschickt" konvertieren muss, aber als ich noch vor einigen Jahren mit VB-6 gearbeitet habe, da wurden die ganzen Castings von C++ in VB "von alleine" durchgeführt. So sollte eine Programmiersprache auch sein: 👍 Ein Hilfsmittel mit dem man bei seinem eigentlichen Problem voran kommt und nicht bei dem man sich recht toll vorkommt nur weil man da und dort "weis wie es geht" (und die "Anderen" nicht) was ja sooo elegant ist. Bei C++ habe ich immer mehr den Eindruck, dass das es immer mehr so eine Freak-Sprache wurde als etwas was der Druchschnittsprogrammierer einfach anwenden und verwenden kann. Alleine, dass es so viele unterschiedliche String-Typen gibt 👎 die nicht so ohne weiteres oder nur mit Kopfständen ineinander umwandelbar sind 😞 bringt mich schon zur Weißglut 😡 . Da will man ein Programm schreiben um ein konkretes Problem zu lösen und dann kämpft man mit den popligen Umwandlungen. Die verschiedenen Typen/Methoden/Klassen sind zwarzwar in der "gleichen" Programmiersprache impementiert aber stehen trotzdem oft wie eine eigene Insel für sich und man kommt kaum zum eigentlichen Problem oder nur deutlich verspätet.

    Nun genug geschimpft. (Auch wenn mir C++ durch sowas unsympathisch ist...)
    Nochmals vielen Dank. 🙂
    Ich finde das Forum hier super und die Hilfe (meist) sehr brauchbar.
    Mein Kompliment an die Macher und Unterstützer von "www.c-plusplus.net" 😃 !!!



  • Gastleser schrieb:

    Ich verwende die Visual Express C++ 2008 und da gibts offenbar kein "CString".

    1. Doch den gibt es in EE 2008. Nur Du schreibst in C++/CLI und nicht in der MFC oder ISO C++.

    2. Dann kannst Du auch die Code-Tags benutzen.
    3. Du musst lernen die Hilfen von MS richtig zu lesen, es werden Grundsätzlich immer die Namespace und #includs aufgelistet.
    4. VB 6 ist nun schon lange Tod.



  • zu "1. Doch den gibt es in EE 2008. Nur Du schreibst in C++/CLI und nicht in der MFC oder ISO C++."
    Wo und Wie geht das?
    Jetzt heißt gleich wieder "der weis ja gar nichts was sucht der hier", aber ich habe auch die MS-Hilfe durchsucht auf MFC und CLI aber nach einigen Minuten nichts gefunden wie man da was und wo so einstellt das dies oder jenes geht. Da wird dann wieder mit anderen Spezialbegriffen ein Spezialbegriff erklärt und so vergeht die Zeit... Gibts da vielleicht igengwo im Internet eine Seite die das konkret für "Quartals-Programmierer" erklärt?

    zu "2. " die Hilfen richtig lesen
    Es gibt genug Beispiele in der MS-Hilfe die nur als Code-Schnipsel ausgeführt sind. Da fehlt nicht nur die main sondern auch der obere include und namespaces-Teil. Aber ich verstehe durchaus, dass es nicht immer möglich ist ein ausführliches Beispiel zu bringen. Die Hilfe wird auch dann ausführlicher wenn man sich die 2,5GB große Visual-Lib runterlädt... na ja, je länger man sich mit was beschäftigt desto mehr weis man drüber (vielleicht gehts darum? Momo und die Grauen Männer 😉 ).

    zu "4. VB 6 ist nun schon lange Tod."
    ...offenbar auch die Zeit von Programmiersprachen bei denen man auch kleinere Probleme 'schlampig' (quick & dirty) lösen konnte - d.h. mit nur eingeschränkten Kenntnissen in der jeweiligen Programmiersprache. Schon wenn man eine Bildschirmausgabe von Text, Zahl und String gemischt machen möchte wirds bei einigen sehr schwierig.

    Übrigens:
    Es gibt nicht nur Leute die sehr gerne Programmieren, einige wollen (konnten) es nur um sich ein konkretes PC-Problem (Berechnungen usw.) 'vom Halse' zu schaffen. Dahingehend war mein Kommentar gemeint.
    So erinnere ich mich noch an das GFA-Basic des Atari ST (ich höre schon das Aufstöhnen und die Verdammnis-Sprüche) bei dem sogar Grafik-Ausgaben auf einfache Art und Weise möglich waren. Mir ist natürlich bewußt, dass die Entwicklung weiter gegangen ist usw. So würde ich nicht auf das Multitasking verzichten wollen usw. Trotzdem düfte diese immer höher werdende Hürde für das Verständnis moderner Programmiersprachen die Entwicklung hin zum Elfenbeinturm nur noch beschleunigen. Die Mehrheit der Computer-Nützer sind somit generell zum reinen "usen" verurteilt. Die "Freaks" unter den "Normalos" können dann eventuell noch so leidlich VBA und dann ist's auch schon vorbei.

    Trotzdem finde ich das Forum hier (meist) sehr hilfreich, besonders bei der (hilfreichen) Beantwortung von diversen Fragen (wie weiter oben geschehen).

    MFG 😃 !


Anmelden zum Antworten