none
VS2010 C++, MFC .NET C# Assembly - Vorgehensweise, Beispiel

Antworten

  • Freigeben muss sein. Und als Parameter muss man den IntPtr übergeben, den man vom StringToHGlobalX erhalten hat.

    Im Beispiel hab ich den direkt per "ToPointer()" in einen void* gecastet und dann nach wchar_t* ... aber du kannst hier auch einen anderen Weg wählen wie z.B. den IntPtr zwischenspeichern statt am Ende wieder casten.

    • Als Antwort markiert Andy Bauer Montag, 18. Februar 2013 19:12
    Sonntag, 17. Februar 2013 15:11

Alle Antworten

  • Nun ja... du hast ja dein MFC Projekt... dann aktiviere mal CLR... das soll so gehen

    http://msdn.microsoft.com/de-de/library/ms235211(v=vs.80).aspx

    ... ausprobiert hab ich's nicht. Aber danach müsstest du zu deinem Projekt eine verwaltete Klasse hinzufügen können und die ansteuern (würde ich als Test mal ausprobieren).

    Wenn das geht, musst du (theoretisch) nur noch den Verweis sezten (wie du das bebildert hast) und dann den richtigen Namen für den Aufruf der Klasse verwenden. Den hol ich mir jeweils aus dem Fenster "Objektkatalog" ... da kann man irgendwie die Assembly angeben, dann listet's einem auf was da drin ist.

    ... wie gesagt, ausprobiert hab ich das so direkt nicht. Aber in Projekten ohne MFC hab ich das schon so gemacht.

    Rudolf

    Freitag, 15. Februar 2013 21:07
  • Nun ja... du hast ja dein MFC Projekt... dann aktiviere mal CLR... das soll so gehen

    http://msdn.microsoft.com/de-de/library/ms235211(v=vs.80).aspx

    Hallo Rudolf,

    danke mal. Die Einstellungen habe ich vorgenommen.

    http://msdn.microsoft.com/de-de/library/ms235211(v=vs.100).aspx

    C# Namespace RGROUP1.ElementA.ConnectorA.Core

          public   Class ConnectorA

                 void Func1();

                 int Func2(int a, string b);

                string Func3(double a, decimal b);

    Kannst Du kurz aufzeigen

      A) Wie erzeugst du ein Objekt in der MFC?

      B) Aufrudf der 3 Funktionen mit Rückgabe String  (CString)

    Danke und Grüße Andy

    Samstag, 16. Februar 2013 15:49
  • Hallo

    A) Das kannst du über die C++/CLI Sprachelemente machen, die man mit native C++ mixen kann. Mit gcnew (anstelle von new) kannst du so ein verwaltetes Objekt erzeugen. Also (mal ganz ohne using's)

    RGROUP1::ElementA::ConnectorA::Core::ConnectorA^ pMyObject = gcnew RGROUP1::ElementA::ConnectorA::Core::ConnectorA();

    das ^ entspricht dem *

    B) Der Aufruf geschieht ganz normal mit pMyObject->Func3 und das Resultat ist ein System::String^ ... das muss du dann umwandeln in einen nativen String. Dazu schreibst du am einfachsten

    using namespace Runtime::InteropServices;

    Und dann kannst du mit den Funktionen Marshal::StringToHGlobalUni oder Marshal::StringToHGlobalAnsi den String in einen unmanaged Puffer packen.

    Konkret so:

    System::String^ verwString = pMyObject->Func3(/* was auch immer */);

    wchar_t* strString = (wchar_t *)(Marshal::StringToHGlobalUni(verwString).ToPointer());

    CString das_was_du_willst(strString);

    Marshal::FreeHGlobal((IntPtr)strString);

    ... tja, reichlich kompliziert. :-) aber einfacher geht's nicht, das kann ich dir sagen. Ich habe gerade ein Projekt hinter mir, bei dem's darum ging solchen Marshaling-Code zu generieren.

    Gruss, Rudolf

    Samstag, 16. Februar 2013 17:55
  • using namespace Runtime::InteropServices;

    Und dann kannst du mit den Funktionen Marshal::StringToHGlobalUni oder Marshal::StringToHGlobalAnsi den String in einen unmanaged Puffer packen.

    Konkret so:

    System::String^ verwString = pMyObject->Func3(/* was auch immer */);

    wchar_t* strString = (wchar_t *)(Marshal::StringToHGlobalUni(verwString).ToPointer());

    CString das_was_du_willst(strString);

    Marshal::FreeHGlobal((IntPtr)strString);

    ... tja, reichlich kompliziert. :-) aber einfacher geht's nicht, das kann ich dir sagen. Ich habe gerade ein Projekt hinter mir, bei dem's darum ging solchen Marshaling-Code zu generieren.

    Hallo Rudolf,

    ich teste es und melde mich ggf. nochmals. Ja kompliziert.

    Das komplexe freigeben muss sein?

    Marshal::FreeHGlobal((IntPtr)strString);

    Grüße Andy

    Sonntag, 17. Februar 2013 07:46
  • Freigeben muss sein. Und als Parameter muss man den IntPtr übergeben, den man vom StringToHGlobalX erhalten hat.

    Im Beispiel hab ich den direkt per "ToPointer()" in einen void* gecastet und dann nach wchar_t* ... aber du kannst hier auch einen anderen Weg wählen wie z.B. den IntPtr zwischenspeichern statt am Ende wieder casten.

    • Als Antwort markiert Andy Bauer Montag, 18. Februar 2013 19:12
    Sonntag, 17. Februar 2013 15:11
  • Hallo Wie sieht es bei so einer Mixedmode Anwendung eigentlich mit den klassischen callstacks aus ? Gibt es die jetzt endlich wieder und kann man die inzwischen auswerten oder geht das immer noch nicht ?
    Sonntag, 17. Februar 2013 21:13
  • Gemischte Anwendungen (also in dem Fall jetzt native, welches managed lädt) kann man debuggen, wenn man in der Konfiguration unter "Debuggen" den "Debuggertyp" auf "Gemischt" stellt.

    Andersrum (also z.B. C# lädt C++ native dll) muss man's anders einstellen... aber das findet ihr auch in den Eigenschaften vom Projekt.

    Montag, 18. Februar 2013 16:00
  • Freigeben muss sein. Und als Parameter muss man den IntPtr übergeben, den man vom StringToHGlobalX erhalten hat.

    Im Beispiel hab ich den direkt per "ToPointer()" in einen void* gecastet und dann nach wchar_t* ... aber du kannst hier auch einen anderen Weg wählen wie z.B. den IntPtr zwischenspeichern statt am Ende wieder casten.

    Hallo Rudolf,
    ja Frage mal beantwortet. Danke.
    Grüße Andy

    void CRTestAppMFCDlg::OnBnClickedButton1()
    {
    	//gcroot<RCommunication::Implementations::ConnectorMachineDataCustomerB ^> F_TEST;
    	// ConnectorMachineDataCustomerB fff;
    	RCommunication::Implementations::ConnectorMachineDataCustomerB::Core::ConnectorMachineDataCustomerB ^ pMyObject = gcnew RCommunication::Implementations::ConnectorMachineDataCustomerB::Core::ConnectorMachineDataCustomerB();
    
    	int ret = pMyObject->TestOn_2();
    	int retOriginal = pMyObject->TestOn();

    Montag, 18. Februar 2013 19:12
  • Ja schon klar Aber was ist mit den Dump bzw dmp Dateien um beim absturz den callstack und diverse Variablen zu debuggen bzw. die dmp Datei in den Debugger zu Laden, geht das auch bei gemischten Anwendungen ? Soweit ich mich erinnern kann ging das unter vs2005 bzw. .NET 3.x nicht. Hat sich das inzwischen geändert ?
    Montag, 18. Februar 2013 21:33
  • > Ja schon klar Aber was ist mit den Dump bzw dmp Dateien um beim absturz den callstack und diverse Variablen zu debuggen bzw. die dmp Datei in den Debugger zu Laden, geht das auch bei gemischten Anwendungen ? Soweit ich mich erinnern kann ging das unter vs2005 bzw. .NET 3.x nicht. Hat sich das inzwischen geändert ?

    Zumindest mit WinDbg geht dies... SOS unterstützt hier einen speziellen "MiniDumpMode"...


    Jochen Kalmbach (MVP VC++)
    Dienstag, 19. Februar 2013 06:55