Eine Projektmappe, zwei Assemblies, gemeinsame Arbeit
-
Hallo,
Den ganzen Tag versuche ich nun mehrere Assemblies dazu zu bringen, sich zu verstehen. Ohne Erfolg.
1 Projektmappe mit
1 Hauptassembly (.exe) und
1 Assembly (.dll)Jede Assembly ist ein Projekt in der Projektmappe.
Hauptassembly = Consolenanwendung
Nebenassembly = Klassenbibliothek (vielleicht liegt da das Problem)Die Nebenassembly ist als Verweis in der Hauptassembly angegeben.
#include "Base.h" ... int main(array<System::String ^> ^args) { Base::BaseClass^ bC = gcnew Base::BaseClass(); return 0; }
#pragma once #include "HeaderA.h" #include "HeaderB.h" namespace Base { ref class BaseClass { public: BaseClass(); void Do(void); private: ~BaseClass(); }; }
#include "Base.h" Base::BaseClass::BaseClass() { A::ClassA^ cA = gcnew A::ClassA(); B::ClassB^ cB = gcnew B::ClassB(); }; ...
... namespace B { public ref class ClassB { public: ClassB(); void Do(void); private: ~ClassB(); }; }
... B::ClassB::ClassB() { External::ExternalClass^ eC = gcnew External::ExternalClass(); };
#include "HeaderB.h" namespace External { public ref class ExternalClass { public: ExternalClass(B::ClassB^ Ref); private: ~ExternalClass(); }; }
External::ExternalClass::ExternalClass(B::ClassB^ Ref) { }; ...
HeaderA.h ist analog zu HeaderB.h (ich wollte nur ein bisschen "Struktur" hineinbringen.
Folgende Fehler kommen
Fehler 1 error LNK2020: Nicht aufgelöstes Token (06000001) B.ClassB::.ctor. External.obj
Fehler 2 error LNK2020: Nicht aufgelöstes Token (06000002) B.ClassB::Do. External.obj
Fehler 3 error LNK2020: Nicht aufgelöstes Token (06000003) B.ClassB::~ClassB. External.objExternal ist die Nebenassembly, Assemblies heissen Solution und somit auch die Hauptassembly.
Die Fehler kommen, sobald ich HeaderB in External bekannt mache.
Es geht mir darum, die Hauptassembly pur zu halten (/clrsafe) und in der Nebenassembly Interop zu machen (also /clr). Nur muss ich ja auch (Ref) Objekte oder zumindest Referenzen austauschen können.Ich verstehe auch nicht, warum die Header nicht auch in der Nebenassembly verwendet werden können (zumindest, um einen Typen zu verwenden).
Weiss jemand, wie das richtig geht?
Was mache ich falsch bzw. wie ist die richtige Herangehensweise?
Keine Klassenbibliothek?
Mehrere Projektmappen?
Die Header zusätzlich noch ins Nebenprojekt kopieren?
Oder gibt es eine andere Art der Übergabe?Fragen über Fragen leider.
-
Wenn Du die Assembly verwendest brauchst Du keine Header. Wenn Du die Header includierst, erwartet der Linker entsprechend die Objektdaten zum Linken.
In der Assembly wird durch ein Verweis aber alles importiert was Du brauchst.
Sorge dafür, das alles was Du verwenden willst von der Assembly innerhalb der Assembly mit public makiert ist und Du keine Header der Assembly inkludierst.
-
Also in die eine Richtung funktioniert alles auch wunderbar. Die External.dll wird nur mittels Verweis und ohne include und namespace erkannt.
Das Problem tritt auf, wenn ich gleichzeitig auch noch der External.dll ein Objekt aus der Assemblies.exe übergeben will. Dann braucht External ja die Definition des Objekts aus Assemblies.
Es geht um folgendes:
Ich habe ein Programm (Assemblies.exe). Dieses Programm soll die Objekte der dll (External.dll) verwenden können. Das geht auch.
Nur will ich nun einer Methode in External.dll eine Referenz auf ein Form in Assemblies.exe übergeben, damit diese externe Methode eine Operation ausführen kann. Daher dachte ich, ich müsste zumindest im Sourcecode der externen dll die Headerdatei für das Form includen. Sonst kann ich ja den Typ nicht in der dll verwenden.Wenn ich mir die Fehler so ansehe, dann liegt nahe, dass zwar die HeaderB.h includet wird, aber Header.cpp nicht. Ich habe mal versuchsweise auch den .cpp Teil in die Headerdatei gegeben. Dann sagt mir VS, dass External (also namespace und Klassen der dll) nicht bekannt ist.
Wie kann ich die Übergabe gestalten, ist also die Frage.
-
Na ich sehe da mehr ein Designproblem. External.dll ist direkt abhängig von Anwendung.exe .
Du kannst dann aber den Teil aus Anwendung.exe in die DLL auslagern und dies dann von der DLL in Anwendung.exe laufen lassen oder musst es auf einen gemeinsamen Nenner zurück führen. (System.Windows.Forms.Form) .
-
Es ist ein Problem, weil ich in der dll z.B. unmanaged OpgenGL Funktionen habe. Dadurch will ich mir aber nicht die ganze .exe von einem sauberen /clrsafe auf /clr "verschmutzen" lassen. Darum die Überlegung mit der dll. Also werde ich das wohl einfach als, wie Du sagtest, System::Windows::Forms::Form übergeben.
Ich würde es auch mit Reflection machen, aber da ist mir nicht klar wie ich mir MyForm aus der Hauptassembly hole und damit dann wieder zu "normalem" Code zurückkehren kann.
Also ungefähr so:
Pseudocode ref class ExternalClass { void GetMyForm() { Reflection-Operationen; MyForm = ErgebnisDerReflection-Operationen; }; ... MyForm^ MyRunningForm; }
-
So - Problem doch noch gelöst
Drittes Projekt erstellt. Besagte Header dort integriert. Verweise von den anderen Projekten auf dieses gelegt. Jetzt geht es. Nun ist dadurch zwar noch eine dll mehr dabei, aber es geht.