methoden externer Klassen als inline definieren



  • Hallo,

    Ich habe die Methode einer externen Klasse als inline
    definiert. Wenn die Methode nicht ausserhalb der externen Klasse aufgerufen wird, funktioniert das super.
    Sobald die als inline definierte Methode der externen Klasse
    allerdings innerhalb eines anderen Modules direkt aufgerufen
    werden soll, bekomme ich eine Fehlermeldung.

    Meine erste Frage ist, ob man überhaupt externe Methoden als inline definieren und sie dann in einem anderen Modul aufrufen kann.
    Meine zweite Frage, falls das nicht möglich ist, wäre ob man dieses Problem
    auf anderem Wege umgehen kann.



  • Was auch immer du mit einer externen Klasse meinst, aber wahrscheinlich musst du die inline-Methode nur im Header dieser Klasse definieren, nicht im cpp-File.



  • Mit einer externen Klasse meine ich eine Klasse, die nicht in dem
    Modul definert wird in dem ich ihre Methoden aufrufe.

    Ich habe deinen Vorschlag ausprobiert. Jedoch tritt der selbe Fehler auf:
    error LNK2001: Nichtaufgeloestes externes Symbol "public: void __thiscall ExterneKlasse:methode(int,int)" (?methode@ExterneKlasse@@QAEXHH@Z)
    Debug/main.exe : fatal error LNK1120: 1 unaufgeloeste externe Verweise
    Fehler beim Ausführen von link.exe.



  • Na dann zeig mal ein bisschen Code.



  • Hallo Cream,

    ich hatte neulich das selbe Problem wie Du (hört sich zumindest gleich an). Hier mal kurz wie ich an die Sache rangehen werde und wie ich das ganze verstehe. Da ich weißtgott kein "Guru" in dem bin was beim compilen genau passiert soll mich bitte jeder sofort korrigieren der's besser weiß, nicht das ich was falsches erzähle.

    Nehmen wir an Du hast folgende Klasse, die Du "extern" verwenden möchtest:

    Externe Klasse (bspw. 'cextern.h')

    class CExtern
       {
       public:
          void Method();
          CExtern();
          ~CExtern();
       };
    

    So wie ich Dein Vorhaben verstehe, hast Du eine zu dieser Klassendeklaration gehörige CPP-Datei, z.B. 'cextern.cpp', in der Du die Inline-Methode definierst, z.B. so:

    Definition der Inline-Methode (bspw. 'cextern.cpp')

    inline void CExtern::Method()
       {
       fprintf(stdout, "Extern Method called!\n");
       }
    

    Diese beiden Dateien packst Du jetzt in ein zweites Modul, z.B. eine DLL oder .so-File nehme ich mal an.

    In Deinem Hauptprogramm bindest Du die Lib ein, erstellst ein Objekt vom Typ CExtern und rufst die Inline-Methode auf, wo die unresolved external auftritt:

    Main-Program (bspw. 'main.cpp')

    #include <cextern.h>
    
    int main(int argc, char** argv)
       {
       CExtern Obj;
       Obj.Method();   // Unresolved symbol!
       return 0;
       }
    

    Falls ich soweit damit richtig liege ist die Erklärung denke ich recht einfach: In meiner 'main.cpp' binden wir über 'cextern.h' die KlassenDEKLARATION ein, und verwenden das Objekt mitsamt Methode. Da allerdings die DEFINITON gänzlich fehlt, weiß der Compiler nicht wo die Referenz auf die Methode ist. (Spezialisten: Falls Fehler von mir, bitte schreien!).

    Möglicher Lösungsansatz:

    1. Pack die Definiton der Methode mit in die Klassendeklaration und entferne die .cpp-Datei gänzlich (hast Du glaube ich schon probiert):

    Externe Klasse mitsamt inline Methode(bspw. 'cextern.h')

    class CExtern
       {
       public:
          inline void Method()
             {
             fprintf(stdout, "Extern Method called!\n");
             }
    
          CExtern();
          ~CExtern();
       };
    
    1. Was ich öfter gesehen habe, dass einige die .cpp-Datei beibehalten, sie allerdings mit der Endung .inl versehen, und diese dann am Ende der Header-Datei ganz normal über include einbinden. Hab' ich noch nie probiert, wäre aber nen Versuch wert. Dürfte so aussehen:

    Externe Klasse mit inkludierter inline Methode(bspw. 'cextern.h')

    class CExtern
       {
       public:
          void Method();
    
          CExtern();
          ~CExtern();
       };
    
    #include <cextern.inl>   // Die 'cextern.cpp'-Datei mit .inl Dateiendung
    

    Gruß,
    PuerNoctis 🙂



  • Hallo PuerNoctis,

    Vielen Dank für deine Asuführung.

    Diese beiden Dateien packst Du jetzt in ein zweites Modul, z.B. eine DLL oder
    .so-File nehme ich mal an.
    Ich füge die externe Klasse per #include der header-Datei in eine weitere cpp-Datei,
    die die main Funktion aufruft (und noch die Schnittstelle einer anderen Klasse definiert, was zugegebenermaßen kein guter Stil ist).

    Ich habe weiter versucht das Problem zu lösen und bin zu dem Schluss gekommen,
    dass der Lösungsansatz mit der inline Notation innerhalb der header-Datei
    teilweise funktioniert. Diesen Ansatz halte ich allerdings für schlecht,
    weil meine Methode über ca. 8 Zeilen gehen und die Schnittstellenbeschreibung
    übersichtlicher bliebe, wenn man nur das Schlüsselwort inline vor die
    Methode stellen könnte ohne den ganzen Methodenkörper in die Schnittstelle einzufügen. Ich meine inline ist inline. Wieso wird dabei zwischen mehreren Fällen unterschieden?
    Nun zu dem "teilweise":
    Bei der einen Methode klappt die Deklaration als inline bei der anderen (Methode void klapptnicht()) nicht.
    Bei der Methode klapptnicht() habe ich eine zweite Methode klapptwohl() inline definiert, die genau dasselbe macht. Dann habe ich alle aufrufe von klapptnicht() durch klapptwohl() ersetzt. Das funktioniert sogar. Sobald ich die Methode klapptnicht() nun lösche oder nur einen der zwei Methodenaufrufe im Körper der Methode bekomme ich eine Fehlermeldung:

    error LNK2001: Nichtaufgeloestes externes Symbol "public: void __thiscall externeKlasse::methodeVonKlapptNicht(void)" (?methodeVonKlapptNicht@externeKlasse@@QAEXXZ)
    Debug/main.exe : fatal error LNK1120: 1 unaufgeloeste externe Verweise



  • Heyho Cream,

    hmm.... kannst Du eventuell mal Deinen Code hier posten? Muss jetzt nicht in voller Länge sein, also schmeiss ruhig alle unrelevaten Anweisungen aus den Methoden raus. Wäre sehr hilfreich. Am Besten auch so gliedern, dass man sieht was in welchen Dateien steht und wie was eingebunden wird.

    Gruß,
    PuerNoctis



  • PuerNoctis schrieb:

    Heyho Cream,

    hmm.... kannst Du eventuell mal Deinen Code hier posten? Muss jetzt nicht in voller Länge sein, also schmeiss ruhig alle unrelevaten Anweisungen aus den Methoden raus. Wäre sehr hilfreich. Am Besten auch so gliedern, dass man sieht was in welchen Dateien steht und wie was eingebunden wird.

    Gruß,
    PuerNoctis

    Ich dachte der Fehler den ich mache ist vielleicht bereits bekannt 😢
    Der Code ist recht groß. Den zu kürzen sodass das Problem (welches ich nicht lokalisieren kann) zu verändern würde einiges an Zeitaufwand für mich bedeuten.
    Wenn ich Zeit dazu habe werde ich den Fehler vermutlich selbst finden.
    Sobald ich dazu komme poste ich zumindest die gekürzte Version des Quelltextes.
    Oder gleich die Lösung wenn ich sie gefunden habe.

    Danke für eure Unterstützung!



  • Cream schrieb:

    Ich habe weiter versucht das Problem zu lösen und bin zu dem Schluss gekommen,
    dass der Lösungsansatz mit der inline Notation innerhalb der header-Datei
    teilweise funktioniert. Diesen Ansatz halte ich allerdings für schlecht,
    weil meine Methode über ca. 8 Zeilen gehen und die Schnittstellenbeschreibung
    übersichtlicher bliebe, wenn man nur das Schlüsselwort inline vor die
    Methode stellen könnte ohne den ganzen Methodenkörper in die Schnittstelle einzufügen. Ich meine inline ist inline. Wieso wird dabei zwischen mehreren Fällen unterschieden?

    Inline heißt, dass der Compiler von der Stelle, wo die Funktion aufgerufen wird, den Funktionskörper sehen können muss (damit er ihn, wenn er das für richtig hält, direkt einfügen kann). Das ist natürlich nicht möglich, wenn er nur die Deklaration sieht und die Definition in einem separaten Modul untergebracht ist.
    (Du bist dir ansonsten natürlich darüber im klaren, dass eine Headerdatei nicht dasselbe ist wie eine Schnittstellenbeschreibung, da in einem Header aus technischen Gründen auch Implementationsdetails definiert werden müssen, die logisch gesehen niemanden etwas angehen.)

    Ich dachte der Fehler den ich mache ist vielleicht bereits bekannt 😢

    Dachte ich auch zuerst, aber wenn das offensichtliche nicht hilft ...



  • Das Problem ist soweit gelöst. Ich weiß immer noch nicht genau, was nun
    nicht funktioniert hat. Aber vielleicht finde ich das raus, wenn ich mir Zeit nehme um mich mit dem Problem auseinanderzusetzen. Sonst habe ich die selben Schwierigkeiten beim nächsten Mal wieder 🙂

    THX


Log in to reply