C-Funktionen nach C++ portieren und instanziieren
-
Hallo,
habe ein C-Projekt, das auf einem Mikrocontroller läuft in eine C++-Umgebung eingebunden, damit ich diese als Emulator benutzen kann.
Soweit funktionierts.
Jetzt möchte ich aber in meinem C++-Programm mehrere Instanzen meines C-Projektes laufen lassen...
Bisher habe ich eine Klasse Emulator von der Objekte erzeugt werden können und dann mein C-Programm mit Aufruf der Funktion main() ausführen. Allerdings werden diese C-Funktionen als "static" aufgerufen, d.h. jedes Emulator-Objekt greift auf dieselben Adressen zu.Wie kann ich mein C-Projekt "importieren", dass jeder Emulator sein C-Programm starten kann.
Geht das vielleicht in den Funktionsdeklarationen? Das C-Projekt ist ziemlich umfangreich und importiert so ca. 50 Files.Für Tips wäre ich sehr dankbar.
Grüße Jens
-
Da sind eindeutig mehr Informationen nötig. Zum Beispiel: Was macht dein C++-Programm überhaupt?
-
das C++ Programm ist ein MDI-Framework (weniger wichtig).
Ich erzeuge eine Emulator-Instanz (der Emulator-Klasse) und dieses Objekt startet derzeit die main() des C-Projekts und visualisiert ein paar Daten des C-Projekts in einem Window:In diesem C-Projekt sind natürlich Datenfelder definiert (structs, Variablen, ...).
Wenn ich jetzt eine 2. Emulator-Instanz starte, die dann wieder die main()-Methode des C-Projekts aufruft, greift diese auf dieselben Daten des C-Projekts zu, wie das zuerst erzeugte Objekt.
Das soll aber so nicht sein...Jetzt bin ich auf der Suche nach einer einfachen Lösung, ohne mein C-Projekt nach C++ portieren zu müssen.
-
Entweder verstehe ich da gerade etwas anders als du es meinst oder du hast da den Oberbug aller Zeiten gefunden. Daher vermutlich ersteres. Wie rufst du das C-Programm denn auf? Heißt das etwa, dass das C-Programm kein eigenes Programm ist, sondern in dein C+-Programm eincompiliert wird? Falls letzteres: Tja, so ist das nun einmal, wenn man Nicht-Reentrant-Code mehrmals parallel aufruft. Liegt dann irgendwo zwischen "Selbst schuld!" und "Was hast du erwartet?".Allgemeine Abhilfe wäre jedenfalls, das C-Programm in einem eigenen Prozess laufen zu lassen, statt in einem Thread, wie du es anscheinend jetzt machst. Wie das mit Prozessen&Co geht, ist jedoch stark betriebssystemabhängig, da müsstest du uns deine Plattform verraten.
-
natürlich "selbst schuld" 
ich compiliere das C-Projekt in das C++-Projekt, um im Emulator besser weiterentwickeln zu können.
nun wollte ich das ganze eben soweit erweitern, dass mehrere "C-Projekt"-Instanzen parallel laufen.Du hast richtig eingeschätzt, dass ich das ganze derzeit in einem Thread laufen lasse, um auf die Daten (Visualisierung) zugreifen zu können.
Würde das bei einem Prozess auch noch gehen? Wohl nicht direkt oder?Meine Plattform ist Windows (hier Win7), Visual Studio 2008 und 2010
-
Wenn das C-Programm von globalen Daten abhängt, wird das nicht möglich sein, da es von denen innerhalb deiner exe eben nur eine Instanz gibt...
-
Das C-Programm hat "intern" globale Daten,
genau diese hätte ich gerne aber in meinem C++-Tool instanziiert.Gibt es da keine Möglichkeit?
-
jcp1978 schrieb:
Gibt es da keine Möglichkeit?
Gibt es: Das C Programm so umschreiben, dass es eben keine globalen Daten verwendet.
-
jcp1978 schrieb:
Gibt es da keine Möglichkeit?Gibt es: Das C Programm so umschreiben, dass es eben keine globalen Daten verwendet.
das scheidet leider aus
das C-Programm läuft so wie es ist auf einem Mikroprozessor,
da macht es wenig Sinn, das dort zu ändern.
-
Wieso musst du eigentlich im selben Prozess mehrere "Instanzen" dieses C-Programms haben?
-
Weil dann der Datenaustausch ziemlich einfach zu realisieren ist/wäre.
Im Mikroprozessor kommunizieren die "C-Prozesse" jeweils über CAN.
Hier in meinem Emulator wäre es einfach den CAN-Bus zu simulieren und die einzelen Instanzen untereinander zu "verbinden".
Das wäre zwar auch zwischen Prozessen möglich, aber ich denke nicht ganz so einfach...
-
Es wäre wohl nicht ganz so einfach, dafür aber überhaupt erstmal möglich

-
ich hatte da bei einem anderen Projekt schonmal mit SharedMem zu tun, das ist nicht das Problem...
eher, es ist einfacher n Threads zu verwalten, als n Prozessedeshalb mein Ansatz, aber scheinbar leider eine Sackgasse

-
Naja, es ist technisch nicht unmöglich. Aber wenn du das C-Programm nicht verändern kannst (man könnte einen Metacompiler schreiben der das C-Programm eben in eine C++ Klasse wrapped oder zumindest globale Variablen threadlocal macht, sodass man dann eben pro Instanz einen Thread hat), dann sind mehrere Prozesse wohl die einfachste Lösung. Wenn du für die Kommunikation sowieso einen Bus modellieren willst, dann dürfte das z.B. über Pipes wohl auch nicht so besonders kompliziert zu implementieren sein.
-
wie würde so ein wrapper in etwa aussehen?
-
Na so wie dein C++ Programm ihn haben will^^
-
Interprozesskommunikation ist keine Raketenwissenschaft. Es ist nicht ganz so einfach wie Interthreadkommunikation, aber nicht vor dem man Berührungsängste haben müsste. Pipes wurden dir schon genannt, wenn du es eine Portion abstrakter haben möchtest, kannst du dir ja mal MPI angucken.
-
jcp1978 schrieb:
Das C-Programm hat "intern" globale Daten,
genau diese hätte ich gerne aber in meinem C++-Tool instanziiert.Gibt es da keine Möglichkeit?
Jain.
Du kannst jedes deiner C-Projekte zu einer DLL compilieren.
Dann kannst du unterschiedliche C-Projekte (=unterschiedliche DLLs) nebeneinander laufen lassen. Jede DLL hat eigene Kopien globaler Variablen, also ist alles gut.Was damit nicht geht: du kannst so nicht mehrere Instanzen des selben C-Projekts in deinem Emulator laufen lassen. Die globalen Variablen eines einzelnen Projekts sind ja immer noch nur 1x vorhanden.
Wobei man selbst das mit einem Trick (Hack) umgehen könnte: schreib dir einen "Loader", der die DLL erstmal in irgendein Temp-Verzeichnis kopiert, und ihr dabei einen eindeutigen (im Sinn von "unique") Namen verpasst (GUID oder was auch immer). Die Kopie der DLL lädst du dann mit LoadLibrary.
Wenn ich mich nicht sehr sehr täusche, hätte dann wieder jede Kopie der DLL ihre eigenen globalen Variablen.
Pro Instanz eines Programms die du laufen lassen willst, müsstest du dann eine neue Kopie erzeugen und laden.Da du die DLLs dann mit LoadLibrary lädst, musst du dir alle Funktionen die du in den DLLs aufrufen willst mit GetProcAddress holen. Bei vielen Funktionen kann das viel lästig werden. Üblicherweise macht man es daher so, dass man bloss eine Funktion exportiert, die einen Zeiger auf eine Instanz einer Klasse zurückgibt, deren sämtliche Funktionen "virtual pure" sind. Diese Funktionen kannst du dann über den Zeiger aus dem Emulator-Programm aufrufen, ohne dass du sie mit LoadLibrary holen müsstest oder gar "fest" binden (=über eine import-lib).
Und je länger ich darüber nachdenke, desto besser gefällt mir dieser Hack

Sieh nur zu dass du ausreichend Kommentare schreibst was dein Emulator da macht, und vor allem wieso - damit das der nächste der das Projekt warten muss auch verstehen kann.
-
na also,
nach sowas hab ich gesucht, hatte nur noch nicht viel mit DLLs am Hut,
dann wird´s jetzt Zeit das nachzuholen...1000 Dank an alle und besonders @hustbaer
-
Ja, genau sowas in der Art wollte ich auch schon fast vorschlagen. Aber imo zahlt sich dieses gefrickel nicht wirklich aus, wenn man bedenkt, dass die einzelnen Instanzen sowieso über einen "CAN Bus" kommunizieren sollen. Das bedeutet er muss sowieso ein Bussystem nachbauen. Ob selbiges seine Daten nun durch Pipes schickt oder ob er sich selbst sowas wie Pipes baut, macht dann wohl keinen Unterschied, im Gegenteil. Evtl. ist die Variante mit mehreren Prozessen also nicht nur sauberer, sondern sogar auch noch weniger Implementierungsaufwand.