Wie löse ich einen nicht aufgelösten externen bei der Verwendung von C++ Builder-Pakete?
Ich experimentiere mit der Neukonfiguration meiner Anwendung zu machen, begnügte sich mit Paketen. Beide, ich und ein anderer Entwickler, ein ähnliches experiment in ein wenig Mühe, beim verknüpfen mit mehreren verschiedenen Paketen. Wir sind wohl beide etwas falsch, aber Gott-weiss-was 🙂
Die situation ist folgende:
- Das erste Paket
PackageA.bpl
enthält C++ - KlasseFooA
. Die Klasse wird deklariert mit derPACKAGE
Richtlinie. -
Das zweite Paket,
PackageB.bpl
enthält eine Klasse erbt vonFooA
genanntFooB
. Es umfasstFooB.h
, und das Paket ist gebaut mit Laufzeit-packages und links zuPackageA
durch das hinzufügen einer Referenz zuPackageA.bpi
. -
Beim Bau
PackageB
es kompiliert einwandfrei, aber die Verknüpfung schlägt fehl, mit einer Reihe von nicht aufgelöste externe Verweise, der erste von denen einige sind:[ILINK32 Error] Error: Unresolved external '__tpdsc__ FooA' referenced from C:\blah\FooB.OBJ
[ILINK32 Error] Error: Unresolved external 'FooA::' referenced from C:\blah\FooB.OBJ
[ILINK32 Error] Error: Unresolved external '__fastcall FooA::~FooA()' referenced from blah\FooB.OBJ
etc.
Läuft TDump auf PackageA.bpl
zeigt:
Exports from PackageA.bpl
14 exported name(s), 14 export addresse(s). Ordinal base is 1.
Sorted by Name:
RVA Ord. Hint Name
-------- ---- ---- ----
00002A0C 8 0000 __tpdsc__ FooA
00002AD8 10 0001 __linkproc__ FooA::Finalize
00002AC8 9 0002 __linkproc__ FooA::Initialize
00002E4C 12 0003 __linkproc__ PackageA::Finalize
00002E3C 11 0004 __linkproc__ PackageA::Initialize
00006510 14 0007 FooA::
00002860 5 0008 FooA::FooA(FooA&)
000027E4 4 0009 FooA::FooA()
00002770 3 000A __fastcall FooA::~FooA()
000028DC 6 000B __fastcall FooA::Method1() const
000028F4 7 000C __fastcall FooA::Method2() const
00001375 2 000D Finalize
00001368 1 000E Initialize
0000610C 13 000F ___CPPdebugHook
Also die Klasse definitiv zu sein scheint, exportiert und zur Verfügung link. Ich kann sehen, dass die Einträge für die spezifischen Dinge, die ILink32 sagt es suchen und nicht finden. Läuft TDump auf der BPI-Datei zeigt ähnliche Einträge.
Andere info
Die Klasse unterstützt die Nachfahren von TObject, der ursprünglich vor dem refactoring in Paketen, es war eine normale Klasse in C++. (Mehr Details unten. Scheint es "sicherer" mit den VCL-style-Klassen, wenn Sie versuchen, Probleme zu lösen, mit einem sehr Delphi-ish Sache wie diese sowieso. Ändern Sie dies nur, ändert sich die Reihenfolge der nicht aufgelöste externe Verweise zunächst nicht finden Method1
und Method2
, dann andere.)
Erklärung für FooA
:
class PACKAGE FooA: public TObject {
public:
FooA();
virtual __fastcall ~FooA();
FooA(const FooA&);
virtual __fastcall long Method1() const;
virtual __fastcall long Method2() const;
};
sowie FooB
:
class FooB: public FooA {
public:
FooB();
virtual __fastcall ~FooB();
... other methods...
};
Alle Methoden werden auf jeden Fall umgesetzt .cpp-Dateien, so dass es nicht nicht Sie zu finden, weil Sie nicht existieren! Die .cpp-Dateien enthalten auch #pragma package(smart_init)
in der Nähe der Spitze, unter den includes.
Fragen, die helfen könnten...
- Sind Pakete zuverlässig mit C++, oder sind Sie nur verwendbar mit Delphi code?
- Verknüpft ist das erste Paket, indem Sie einen Verweis auf die BPI-richtige - ist, dass, wie Sie soll, es zu tun? Könnte ich eine LIB aber es scheint, um das zweite Paket viel größer, und ich vermute, es ist statisch gelinkt in dem Inhalt des ersten.
- Können wir
PACKAGE
Richtlinie nur aufTObject
abgeleiteten Klassen? Es gibt keine compiler-Warnung die Verwendung auf standard-C++ - Klassen. - Ist das teilen-code in Pakete der beste Weg, um das Ziel erreichen zu isolieren code und die Kommunikation über definierte Schichten /Schnittstellen? Ich habe die Untersuchung dieser Weg, weil es scheint zu sein, den C++Builder /Delphi Weg, und wenn es funktioniert, es sieht attraktiv aus. Aber gibt es bessere alternativen?
- Ich bin sehr neu in der Verwendung von Paketen und haben nur von Ihnen bekannt, die durch die Nutzung von Komponenten vor. Allgemeine Ratschläge wären toll!
Verwenden wir C++Builder 2010. Ich habe fabriziert, die Klassen-und Methodennamen in den obigen code-Beispiele, aber auch andere, als dass die details sind genau das, was wir sehen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nicht aufgelöstes externes
Nicht aufgelösten externen Verweis in deinem Fall zu sein scheint, da der compiler nicht in der Lage ist, den Weg zu finden, um die Paket-Daten. Sie sollten herausfinden, ob:
Wenn einer von Ihnen wahr ist, dann ist der Weg nicht das problem ist. Aber als Riho auch erwähnt, ist dies die wahrscheinlichste Ursache für das problem. Die Embarcadero Dokumentation wiki besagt Folgendes über die nicht aufgelöstes externes Fehler:
Quelle: Nicht aufgelöstes externes symbol' wird in 'module'.
Da es scheint, von die - zwar veränderte-Klasse Namen - es ist nicht der Fall, der einen Rechtschreibfehler. Sie geben auch an, dass Sie Hinzugefügt haben, das Paket in die requires-Liste, so schließen wir diese als gut. Da Sie nicht die Verknüpfung zu C-Modulen können wir weglassen, das Teil als gut. So weist es auf Probleme mit dem Verzeichnis.
Über die anderen Fragen
Deine Fragen sind alle sehr interessant und viele der Fragen sind Fragen, die ich mein selbst wurde auf der Suche nach Antworten für, wenn ich begann mit der Entwicklung von packages und Komponenten für C++ Builder.
Sind Pakete zuverlässig mit C++?
Pakete sind eine feine Lösung für C++ Builder, C++ Builder gebaut, um die support-packages und der Pascal geschrieben VCL-framework. Dies bedeutet, dass bestimmte Implementierungen unterscheiden sich in C++ Builder als andere Compiler. Dies ist eine Notwendigkeit, um die Sprache kompatibel mit Delphi Geschwister. Aus diesem Grund können Sie Pakete verwenden, die in C++ Builder fast so einfach wie in Delphi.
Verknüpft ist das erste Paket, indem Sie einen Verweis auf seine BPI richtig?
Beginnen mit dem zweiten Teil deiner Frage hier, mit einer lib-Datei macht Ihr Paket größer, weil es einfach mit einer statischen Verknüpfung - so Ihre Vermutung richtig ist. Nun zurück zum ersten Teil der Frage, in Verbindung mit einem Paket in Ordnung ist, indem Sie einen Verweis, um seine BPI. Aber Sie tun müssen, um sicherzustellen, dass die variable path korrekt eingestellt wurde als Riho schlägt in seiner Antwort.
Ich persönlich immer sicherstellen, dass meine Pakete auf die entsprechenden Verzeichnisse in Ihrem Benutzer-Ordner, der Speicherort dieser ist abhängig von Ihrer Delphi-version und die Betriebssystem version. Soweit ich mich erinnern kann ist es unter Dokumente und Einstellungen\alle Benutzer\gemeinsame Dokumente\Rad studio(Versionsnummer)\ - Pakete, aber ich könnte falsch sein darüber.
Können wir
PACKAGE
Richtlinie nur aufTObject
abgeleiteten Klassen?Den
PACKAGE
makro ist aufgelöst in__declspec(package)
können Sie es vergleichen, um__declspec(dllexport)
. Der Unterschied zwischen diesen ist, dass Paket wird verwendet, wenn erklärte in einem Paket, und dllexport wird verwendet, wenn deklariert eine DLL. Es ist ein Thema, über das auf der offiziellen embarcadero Foren mit dem Titel __declspec(package) vs __declspec(dllexport). Der Autor des ursprünglichen Beitrags, fragt auch genau Ihre Frage über diesen, aber leider ist dieser Teil der Frage ist unbeantwortet.Ich habe eine Theorie, aber, und ich muss betonen, dass es nichts mehr als eine Theorie. Remy Lebeau schreibt als Antwort auf die Frage im forum posten:
Also aus der Lektüre seiner Antwort, es scheint mir, dass Paket ist einfach exportieren der Klasse, genau wie dllexport tut. Und da dllexport soweit ich das Lesen kann aus seiner Antwort ist in plain-DLLs werden nur müssen Sie das Paket für den Export von (auch) non-VCL-Klassen aus einem Paket.
Was ist interessant über all das, ist, ein Paket ist im wesentlichen eine DLL, soweit ich mich erinnern kann, aber ich muss zugeben, dass ich nicht finden können, oder erinnern Sie sich an die Quelle dieser Informationen, so nehmen Sie mit einem Körnchen Salz.
, Ist das teilen-code in Pakete der beste Weg, um das Ziel erreichen zu isolieren code?
Pakete haben einige sehr herausragende stärken bei der Erstellung von wiederverwendbaren Komponenten für die VCL. Offensichtlich mit Paketen begrenzt den Benutzer, um entweder C++Builder oder Delphi, aber für die Komponenten geschrieben, um die Vorteile der VCL-framework, es ist eine ausgezeichnete Wahl. Richtig geschrieben können Pakete erleichtern die Wiederverwendbarkeit von Komponenten, und ich glaube, es ist die bevorzugte Methode für die Verteilung von Komponenten für die VCL.
Allerdings, wenn Ihr code hat nicht die Vorteile der VCL-framework in irgendeiner Weise, würde ich erwägen, eine ordentliche Bibliothek, entweder statisch oder dynamisch, einfach, um eine cross-compiler-freundlichen Ansatz.
Ob es der bessere Ansatz ist, zu isolieren, Ihren code, hängt wirklich davon ab, das Projekt an dem Sie arbeiten. Ich mag zu halten, code, kommuniziert durch den Einsatz von VCL-Klassen in Paketen, sondern code, der nicht benötigen Nutzung alle VCL-Klassen in regelmäßigen Bibliotheken. Beachten Sie aber, dass Sie problemlos verwenden können, VCL-Klassen in einer DLL aber Sie brauchen, um zu behandeln besonderen Fällen, wenn Sie die export-Funktionen mit VCL-String-Klassen als Parameter oder Rückgabewerte.
Allgemeine Ratschläge?
Ich bin nicht der erfahrenste Entwickler der Pakete selbst, aber ich habe festgestellt, dass das deaktivieren von runtime-linking oft löst viele meiner Probleme, es ist zwar etwas trivial, um alle Probleme zu beheben, die für Ihren eigenen code, können Sie oft laufen in 3rd-party-Komponenten, die Schwierigkeiten haben, den Umgang mit dieser. Having said, die, ich bin kein fan der Weitergabe meiner Pakete zusammen mit meiner Anwendung als erforderlich in diesem Fall. Aber um ehrlich zu sein, das ist eine Frage des Geschmacks.
Ich persönlich fand es schwer zu finden, einige richtige Antworten auf viele meiner Fragen, als ich anfing, das erstellen der Komponenten und Pakete. Die offizielle Hilfedatei ist nicht die informativ in der Sache, aber ein Blick über den VCL-source-code, wird oft geben Ihnen die beste Antwort auf Ihre Frage. Außerdem gibt es noch ein paar andere websites, die Ihnen helfen können, viele der Seiten sind bestrebt, Delphi zwar, aber dies haben Sie zu gewöhnen, obwohl.
Delphi Wikia hat ein paar gute Artikel über die Erstellung von Komponenten, insbesondere Erstellen Von Komponenten und Erstellen Von Paketen Es ist auch BCB-Journal das ist einer der wenigen C++ Builder bestimmte Seiten, es hat einige schöne Artikel und ein akzeptables forum. Die Delphi-Seiten in About.com ist auch eine gute Quelle von Informationen, die ich gefunden habe, viele gute Tipps und schön, weiß, dass es, insbesondere: Erstellen Benutzerdefinierter Delphi-Komponenten, - Innen und außen.
Vielleicht eine dumme Frage, aber sind deine BPI/BPL-Dateien in den korrekten Pfad gefunden werden, die von linker?
Ich erstellt, sobald eine app im BCB5, dass mehrere verknüpfte Pakete, aber kann mich nicht erinnern, wenn es war etwas besonderes in der Herstellung.
Für mich #pragma package(smart_init,weak) in der cpp-Datei das problem gelöst. Siehe auch http://flylib.com/books/en/3.264.1.27/1/
Die cpp->obj-Datei wird staticly verbunden, ohne Beeinflussung etwas anderes.