Frage

Diese Frage wird im Zusammenhang href="https://stackoverflow.com/questions/232926/how-to-make-consistent-dll-binaries-across-vs-versions"> zum

  • Wir haben Anwendungen und DLLs gebaut mit VC6 und einer neuen Anwendung gebaut mit VC9. Das VC9-App hat zu verwenden, DLLs mit VC6 zusammengestellt, die meisten die in C geschrieben und in einem C ++.
  • Die C ++ lib ist problematisch wegen Name Dekoration / Mangeln Fragen.
  • Kompilieren alles mit VC9 ist derzeit keine Option, da es erscheinen einige Nebenwirkungen. wäre diese Lösung recht zeit raubend.
  • Ich kann die C ++ ändern Bibliothek, jedoch muss sie mit VC6 kompiliert werden.
  • Die C ++ lib ist im Wesentlichen ein OO-Wrapper für eine andere C-Bibliothek. Die VC9-App nutzt einige statische Funktionen sowie einige nicht-statisch.

Während die statischen Funktionen können mit so etwas wie

behandelt werden
// Header file
class DLL_API Foo
{
    int init();
}

extern "C"
{
    int DLL_API Foo_init();
}

// Implementation file
int Foo_init()
{
    return Foo::init();
}

es ist nicht so einfach, mit den nicht-statischen Methoden.

Wie ich es verstehe, Chris Beckes Vorschlag eine COM-ähnliche Schnittstelle wird mir helfen, nicht, weil die Schnittstelle Mitgliedsname noch eingerichtet werden und somit nicht zugänglich von einem binären mit einem anderen Compiler erstellt. Bin ich richtig da?

Wäre die einzige Lösung sein, eine C-Stil DLL-Schnittstelle zu den Objekten mit Handler zu schreiben oder bin ich etwas fehlt? In diesem Fall, ich denke, würde ich wahrscheinlich weniger Mühe hat mit direkt auf die eingewickelt C-Bibliothek.

War es hilfreich?

Lösung

Schnittstelle Elementnamen werden nicht dekoriert werden - sie sind ausgleicht nur in einer V-Tabelle. Sie können eine Schnittstelle (mit einer C-Struktur, sondern als ein COM „Schnittstelle“) definieren, die in einer Header-Datei, so:

struct IFoo {
    int Init() = 0;
};

Dann können Sie eine Funktion aus dem DLL exportieren, ohne Mangeln:

class CFoo : public IFoo { /* ... */ };
extern "C" IFoo * __stdcall GetFoo() { return new CFoo(); }

Das wird funktionieren, vorausgesetzt, dass Sie einen Compiler verwenden, die kompatibel vtables erzeugt. Microsoft C ++ hat das gleiche Format VTable erzeugt, da (zumindest glaube ich) MSVC6.1 für DOS, wo die V-Tabelle eine einfache Liste von Zeigern auf Funktionen (mit Thunk in der Mehrfachvererbung Fall). GNU C ++ (wenn ich mich richtig erinnere) erzeugt vtables mit Funktionszeigern und relativen Offsets. Diese sind nicht miteinander kompatibel.

Andere Tipps

Das größte Problem zu berücksichtigen, wenn eine DLL mit einer anderen C ++ Compiler kompilierte unter Verwendung als die anrufende EXE-Speicherzuordnung und Objektlebensdauer.

Ich gehe davon aus, dass Sie hinter dem Namen bekommen können Mangeln (und Aufrufkonvention), das ist nicht schwer, wenn Sie einen Compiler mit kompatibelen Mangeln verwenden (ich glaube, VC6 mit VS2008 breit kompatibel ist), oder wenn Sie extern verwenden "C".

Wenn Sie Probleme werden, wenn Sie etwas mit new (oder malloc) zuweisen aus der DLL, und Sie kehren dann diese an den Anrufer. Der Anrufers delete (oder free) wird versuchen, das Objekt aus einem anderen Haufen zu befreien. Das geht schief.

Sie können entweder tun, um eine COM-Stil IFoo::Release Sache oder eine MyDllFree() Sache. Beide, weil sie wieder in die DLL aufrufen, wird die korrekte Umsetzung der delete (oder free()), so werden sie das richtige Objekt löschen.

Alternativ können Sie sicherstellen, dass Sie LocalAlloc verwenden (zum Beispiel), so dass die EXE und das DLL den gleichen Heap verwendet wird.

Nun, ich denke Chris Becke Vorschlag ist gut so. Ich würde nicht Roger erste Lösung , die eine Schnittstelle verwendet, in Namen und nur, wie er erwähnt, kann Probleme inkompatibler Compiler-Umgang mit abstrakten Klassen und virtueller Methoden ausgeführt werden. Roger verweist auf den attraktiven COM-consistent Fall in sein Follow-on .

  1. Der Schmerz Punkt: Sie müssen lernen, COM-Schnittstelle Anfragen zu machen und richtig mit IUnknown, die sich auf mindestens IUnknown beschäftigen: AddRef und IUnknown: Veröffentlichung. Wenn die Implementierungen der Schnittstellen können mehr als eine Schnittstelle unterstützt oder wenn Methoden auch Schnittstellen zurückkehren können, können Sie auch mit IUnknown komfortabel brauchen zu werden. Query-Interface

  2. Hier ist der Schlüssel Idee. Alle Programme, die die Implementierung der Schnittstelle verwenden (aber implementiere es nicht) verwenden eine gemeinsame #include „* .h“ Datei, die die Schnittstelle als eine Struktur (C) oder eine C / C ++ Klasse (VC ++) definiert oder struct (non VC ++ aber C ++). Die * .h-Datei paßt sich automatisch entsprechend je nachdem, ob Sie ein C-Language-Programm oder ein C ++ Sprachprogramm kompilierten. Sie müssen wissen, nicht über diesen Teil einfach die * .h-Datei zu verwenden. Was die * .h-Datei tut, ist die Schnittstelle Struktur oder Art definieren, kann sagen, IFoo mit seinem virtuellen Elementfunktion (und nur Funktionen, keine direkte Sicht auf Datenelemente in diesem Ansatz).

  3. Die Header-Datei ist konstruiert, um die COM Binärstandard in einer Art und Weise zu ehren, die für C arbeitet und das funktioniert für C ++, unabhängig von der C ++ Compiler, der verwendet wird. (Das Java JNI Volk rechnete diese heraus.) Das bedeutet, dass es zwischen separat kompilierten Modulen jeglicher Herkunft, solange eine Struktur, bestehend vollständig funktions Eintrag Zeigern (a VTable) arbeitet, ist das gleiche von allen von ihnen in dem Speicher gemappt (so müssen sie alle x86 32-Bit sein, oder alle x64, zum Beispiel).

  4. In der DLL, die die die COM-Schnittstelle über eine Wrapper-Klasse von einer Art implementiert, müssen Sie nur eine Fabrik Einstiegspunkt. So etwas wie ein

    extern "C" HRESULT MkIFooImplementation (void ** ppv);

, die gibt einen HRESULT (Sie müssen über diejenigen lernen) und wird auch eine * pv in einem Ort zurückkehren Sie sorgen für den IFoo Interface-Zeiger zu empfangen. (Ich bin Abschöpfen und es gibt mehr Liebe zum Detail, dass Sie hier benötigen. Sie meine Syntax vertrauen nicht) die eigentliche Funktion Klischee, dass Sie für diesen Einsatz auch in der * .h-Datei deklariert wird.

  1. Der Punkt ist, dass die Fabrik Eintrag, der immer ein undecorated extern „C“ ist tut alle erforderlichen Wrapper-Klasse-Erstellung und liefert dann eine IFoo Schnittstelle Zeiger auf die Stelle, die Sie angeben. Dies bedeutet, dass alle Speicherverwaltung für die Erstellung der Klasse, und alle Speicherverwaltung es für den Abschluss, usw., in der DLL passieren werden, wo Sie den Wrapper bauen. Dies ist der einzige Ort, wo man mit den Details beschäftigen muß.

  2. Wenn Sie ein OK-Ergebnis aus der Fabrik Funktion zu erhalten, haben Sie einen Schnittstellenzeiger ausgegeben worden, und es wurde für Sie bereits reserviert (es gibt eine implizite IFoo: AddRef Betrieb bereits im Namen des Interface-Zeigers ausgeführt Sie wurden geliefert).

  3. Wenn Sie mit der Schnittstelle fertig sind, Sie lassen ihn mit einem Anruf auf dem IFoo: Release-Methode der Schnittstelle. Es ist die letzte Release-Implementierung (falls Sie mehr AddRef'd Kopien), die die Klasse und ihre Schnittstelle Unterstützung in der Fabrik DLL abzureißen. Dies ist, was Sie richtig Vertrauen auf eine konsequente dynamische stoorage Zuweisung und Freigabe hinter der Schnittstelle bekommt, ob die DLL containing die Fabrik Funktion die gleichen Bibliotheken wie der anrufenden Code verwendet.

  4. Query-Interface (als Methode IFoo: Query-Interface) zu, auch wenn es nicht immer
  5. Sie sollten wahrscheinlich IUnknown implementieren. Wenn Sie mit der Verwendung des COM Binärschnittstelle Modell sein anspruchsvollere wollen, wie Sie mehr Erfahrung haben, können Sie lernen, voll Query-Interface-Implementierungen zur Verfügung zu stellen.

Dies ist wahrscheinlich zu viel Information, aber ich wollte viele der Probleme hinweisen, dass Sie über heterogene Implementierungen von DLLs konfrontiert sind in der Definition der COM Binärschnittstelle aufgelöst und selbst wenn Sie nicht brauchen alle es ist die Tatsache, dass es Lösungen gearbeitet bietet, ist wertvoll. Nach meiner Erfahrung, sobald man den Dreh dieser, werden Sie nie vergessen, wie mächtig diese in C ++ sein kann und C ++ Interop-Situationen.

Ich habe nicht die Ressourcen, skizzierte die Sie benötigen für Beispiele beraten und was Sie haben, um zu erfahren, * .h Dateien zu machen und tatsächlich Fabrik-Funktion Wrapper der Bibliotheken, die Sie teilen möchten, zu implementieren. Wenn Sie wollen, tiefer graben, Holler.

Es gibt andere Dinge, die Sie auch schon daran gedacht, wie der Laufzeit von den verschiedenen Bibliotheken verwendet werden. Wenn keine Objekte in Ordnung, das ist geteilt werden, aber das scheint ziemlich unwahrscheinlich, auf den ersten Blick.
Chris Beckers Vorschläge sind ziemlich genau - mit einem ist COM-Schnittstelle kann Ihnen helfen, die binäre Kompatibilität erhalten Sie benötigen. Ihre Ergebnisse können variieren:)

nicht Spaß, Mann. Sie sind für eine Menge Frustration, sollten Sie wahrscheinlich diese geben:

  

Wäre die einzige Lösung sein, ein schreiben   C-Stil DLL-Schnittstelle-Handler mit   zu den Objekten oder bin ich fehlt   etwas? In diesem Fall denke ich, ich   würde wahrscheinlich weniger Mühe haben mit   direkt auf die eingewickelt C-Bibliothek.

ein wirklich genauer Blick. viel Glück.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top