managed Methode von "not managed" Funktion aus aufrufen
-
Hallo,
hoffe ihr könnt mir weiterhelfen:
ein Reduziertes Beispiel:public ref class traceDialog : public System::Windows::Forms::Form { public: void addFrame(const CanFrame & Frame) {...} };
#ifdef _MANAGED #pragma unmanaged #endif class receiver { public: receiver(gcroot<traceDialog^> TraceDialog): m_traceDialog(TraceDialog) {} protected: void onReceivedFrame(const CanFrame & Frame) {m_traceDialog->addFrame(Frame);} // <---- Fehler private: gcroot<traceDialog^> m_traceDialog; };
Beim kompilieren kommt folgende Fehlermeldung:
error C3642: 'traceDialog gcroot<T>::operator ->(void) const' : cannot call a function with __clrcall calling convention from native codeDas ganze läuft unter VC++ 2005 Express.
Die receiver-Klasse lässt sich leider nicht in "managed" verwandeln, da auf
diverse Treiber zurückgegriffen wird, welche dann ihren Dienst verweigern...Bin für jede Anregung dankbar.
Martin
-
Das geht nicht. Du kannst in "unmanaged" code keine Managed Klasse verwende, auch nicht mit "gcroot"!
Du bringst da was durcheinander:
1. Es gibt C++ Klassen, die nicht managed sind (also kein ref), aber trotzdem in IL übersetzt werden; hier kannst Du gcroot verwenden
2. Es gibt wirklich native-C++-Klassen, diese können aber keine Verweise auf managed Objekte enthalten (bis auf void* via GCHandle).
-
erstmal danke für die schnelle Antwort.
Heisst das, ich hab keine Chance, meiner gemanagedten GUI irgendwie
mitzuteilen, dass in einer nicht gemanagedten Klasse ein neuer Frame
empfangen wurde?Langsam fang ich an, das CLR - Zeug abgrundtief zu hassen...
zu 2)
laut http://msdn2.microsoft.com/en-us/library/aeb4be4k.aspx ist
gcroot<T> bloss ein Wrapper für GCHandle.
Und das Halten an sich macht auch keine Probleme.
Erst wenn ich damit was anstellen will, dann krachts.thx
Martin
-
ein dirty workaround:
/////////////////////////////////////////////////////// // hpp /////////////////////////////////////////////////////// class receiver { public: receiver(gcroot<traceDialog^> TraceDialog); protected: void onReceivedFrame(const CanFrame & Frame); private: gcroot<traceDialog^> m_traceDialog; }; /////////////////////////////////////////////////////// // cpp /////////////////////////////////////////////////////// #ifdef _MANAGED #pragma unmanaged #endif receiver::receiver(gcroot<traceDialog^> TraceDialog): m_traceDialog(TraceDialog) {} #pragma managed gcroot<traceDialog ^> dlg; CanFrame frm; void test() { dlg->addFrame(Frame); } #pragma unmanaged void receiver::onReceivedFrame(const CanFrame & Frame) { dlg = m_traceDialog; frm = Frame; test(); }
Jetzt kompiliert er's.
Allerdings kommt jetzt zur Laufzeit eine Exception, dass auf den dialog von einem anderen Thread aus zugegriffen worden ist, als von dem, wo er erzeugt
worden ist...Aber dazu mach ich evtl. später nen neuen Thread auf...
Martin
-
anonymus schrieb:
Jetzt kompiliert er's.
Allerdings kommt jetzt zur Laufzeit eine Exception, dass auf den dialog von einem anderen Thread aus zugegriffen worden ist, als von dem, wo er erzeugt
worden ist...Aber dazu mach ich evtl. später nen neuen Thread auf...
Martin
Tust du ja auch, dann musst du mit (Begin)Invoke und Delegates auf die GUI zugreifen.
-
Auf GUI-Elemente darf man nur aus dem Thread zugreifen, welcher das Element erstellt hat! Und wenn Du es doch willst, so musst Du es, wie Talla sagt, mittels Invok/Begin/EndInvoke machen.
-
anonymus schrieb:
erstmal danke für die schnelle Antwort.
Heisst das, ich hab keine Chance, meiner gemanagedten GUI irgendwie
mitzuteilen, dass in einer nicht gemanagedten Klasse ein neuer Frame
empfangen wurde?Langsam fang ich an, das CLR - Zeug abgrundtief zu hassen...
Die binaries sind halt nicht kompatibel. Das eine wird vom Standard C++ Compiler erzeugt, das andere vom JIT-Compiler der VM. Ich würde nicht mal auf die Idee kommen, dass da irgendwas kompatibel sein könnte.
Wenn du auf bestimmte Module angewiesen bist, musst du deren Objekt-Modell benutzen und zwischen ihnen übersetzen. Unter Windows ist das eigentlich fast immer COM oder .Net oder C-DLLs, war schon immer so, dass man irgendeinen Anhaltspunkt braucht. Von .Net aus kannst du alles nutzen, von COM aus kannst du COM und .Net nutzen. Wenn dir der Sourcecode vorliegt, kannst du alles auch einfach zu IL-Code compilieren, das sollte am wenigsten stressen.
-
ok, also jetzt läufts:
#pragma managed void receiver::onReceivedFrame(const CanFrame & Frame) { m_traceDialog->addFrame(Frame); } #pragma unmanaged
und die addFrame Methode:
delegate void InvokeDelegate(System::Object ^ Line); void traceDialog::test(System::Object ^ Line) { m_listBoxTrace->Items->Add(Line); m_listBoxTrace->SetSelected(m_listBoxTrace->Items->Count - 1, true); } void traceDialog::addFrame(const CanFrame & Frame) { System::Object item; // hier das item befüllen if (this->InvokeRequired == true) { this->BeginInvoke(gcnew InvokeDelegate(this, &traceDialog::test), item); return; } }
Also nochmal danke