[Solved] DLL-Compiler Error



  • Hallo.

    Wenn ich meine DLL erstellen möchte, bekomme ich folgende Fehlermeldung:

    `

    Fehler 1 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""int __cdecl CalcBarFluxCoefficient(struct TMesh *)" (?CalcBarFluxCoefficient@@YAHPEAUTMesh@@@Z)" in Funktion ""int __cdecl CalcSecondElementSpecificationsFkt(struct TMesh *,unsigned int)" (?CalcSecondElementSpecificationsFkt@@YAHPEAUTMesh@@I@Z)". ...\CF2D_Kernel.obj CF2D_Kernel

    `

    Also, CF2D_Kernel ist der Name des Programms, CalcBarFluxCoefficient ist eine Funktion in einem Header File, genauso wie CalcSecondElementSpecificationFkt, welche CalcBarFluxCoefficient aufruft.

    Das ganze sieht in etwa so aus (unten geht die Erklärung weiter):

    #ifndef INCLUDINGS_H
    	#define INCLUDINGS_H
    	#include "Includings.h"
    #endif
    
    #ifndef MESHASSOCIATION_H
    	#define MESHASSOCIATION_H
    	#include "MeshAssociation.h"
    #endif
    
    static TMesh** pMesh = NULL;
    static unsigned int nMesh = 0;
    
    extern "C" __declspec(dllexport) int CalcElementSpecifications(unsigned int MeshIndex, unsigned int Output){
    	if (MeshIndex < nMesh){CalclulateElementSpecificationFkt(pMesh[MeshIndex]); }
    	return 0;
    }
    

    Includings.h

    //...
    #ifndef C_STRUCTS_H
    	#define C_STRUCTS_H
    	#include "C_Structs.h"
    #endif
    
    #ifndef MESHASSOCIATION_H
    	#define MESHASSOCIATION_H
    	#include "MeshAssociation.h"
    #endif
    //...
    

    C_Struct.h

    //Hier sind alle Structuren definiert z.B.
    typedef struct TPoint{
    	double x, y, z;
    }TPoint;
    
    typedef struct TVector{
    	double vx, vy, vz;
    }TVector;
    //uvm.
    

    MeshAssociation.h

    #ifndef INCLUDINGS_H
        #define INCLUDINGS_H
        #include "Includings.h"
    #endif
    
    int CalcSecondElementSpecificationsFkt(TMesh* M, unsigned int Output);
    int CorrectBarElementNumbering(TMesh *M);
    
    int CalcBarFluxCoefficient(TMesh *M){
    	unsigned long fi=0;
    	TElement *B=NULL;
    
    	for(fi=M->nAreaElement;fi<M->nAreaElement + M->nLineElement;fi++){
    		B=&M->pElement[fi];
    		B->DDiff=(double*)calloc(1, sizeof(double));
    		B->NDiff=(double*)calloc(1, sizeof(double));
    		B->DDiff[0] = B->E[0]->DDiff[B->NIndex[0]];
    		B->NDiff[0] = B->E[0]->NDiff[B->NIndex[0]];
    	}
    
    	return 0;
    }
    
    int CalcSecondElementSpecificationsFkt(TMesh* M, unsigned int Output){
    //...
    CalcBarFluxCoefficient(M);
    //...
        return 0;
    }
    

    Das ist sehr komisch, denn das ist in etwa die 50ste Funktion in diesem Projekt, die ich exportiere. Ok, das Headerfile MeshAssociation habe ich zum Projekt hinzugefügt.

    Hat jemand eine Idee?

    Vielen Dank im Voraus.

    Gruß,
    CJens


  • Mod

    Das ist kein Compilerfehler, sondern ein Linkerfehler

    Vermutlich hat es nicht direkt mit deinem Problem zu tun, aber:
    -Keine (nicht-inline) Definitionen in Headern! Das sollte eigentlich jede Menge Mehrfachdefinitionen erzeugen anstatt der hier gezeigten fehlenden Definition 😕
    -Deine Includeguards sind nicht gut*. Du überlässt die Pflicht zur Setzung der Guards demjenigen, der das Include macht. Derjenige kann (und wird mit aller Wahrscheinlichkeit, da es nicht immer unbedingt die gleiche Person ist und die Guards über viele Dateien hinweg koordiniert werden müssen) dabei Fehler machen. Du selbst hast da schon einige Strukturen erzeugt, die zu unerwünschten Ergebnissen führen können, je nachdem, von wo du deinen Übersetzungsprozess startest. Mach die Includeguards in den jeweiligen Header!
    -Ein Gott-Header, der alles included, geht irgendwie am Sinn der ganzen Geschichte vorbei und wird später (oder vielleicht jetzt schon?) höchstwahrscheinlich zu Problemen führen.

    Vielleicht ist eines dieser Probleme schon die Ursache für deinen Fehler. Behoben werden müssen sie auf jeden Fall alle.

    *: Höflich ausgedrückt.



  • SeppJ schrieb:

    Vermutlich hat es nicht direkt mit deinem Problem zu tun, aber:
    -Keine (nicht-inline) Definitionen in Headern! Das sollte eigentlich jede Menge Mehrfachdefinitionen erzeugen anstatt der hier gezeigten fehlenden Definition 😕

    Meinst Du meine meine Funktionen? Ich möchte es verstehen. Wieso soll man die mit inline definieren?

    SeppJ schrieb:

    -Ein Gott-Header, der alles included, geht irgendwie am Sinn der ganzen Geschichte vorbei und wird später (oder vielleicht jetzt schon?) höchstwahrscheinlich zu Problemen führen.

    Ok. Wie macht man es statt dessen? Ich meine, ich habe jetzt schon 20 Headerdateien. Ich will das nicht alles im Main stehen haben. Aber Du hast Recht - es macht Probleme. Manche Header (ich habe da noch kein System erkannt) muss ich dann nochmal einbinden, wobei mein Guard dafür sorgt, dass da nichts doppelt eingebunden wird. Bisher schreibe ja nur ich selbst an dem Programm, aber ich werde die jetzt in die HeaderFiles selbst schreiben.


  • Mod

    CJens schrieb:

    SeppJ schrieb:

    Vermutlich hat es nicht direkt mit deinem Problem zu tun, aber:
    -Keine (nicht-inline) Definitionen in Headern! Das sollte eigentlich jede Menge Mehrfachdefinitionen erzeugen anstatt der hier gezeigten fehlenden Definition 😕

    Meinst Du meine meine Funktionen? Ich möchte es verstehen. Wieso soll man die mit inline definieren?

    Das sollte keine Anweisung sein, die Funktionen (und das gilt auch für alles andere!) inline im Header zu definieren, sondern eher, dass du sie gar nicht im Header definierst. Und wenn es aus irgendeinem Grund doch im Header sein muss, dann muss es auch inline sein (oder theoretisch ginge auch static, aber das wäre irgendwie komisch, etwas static im Header zu haben). Was passiert denn, wenn ein Header mit nicht-inline Definitionen von zwei oder mehr Übersetzungseinheiten eingebunden wird? Dann hast du für jeder dieser Einheiten eine eigene Definition und das darf nicht sein.

    SeppJ schrieb:

    -Ein Gott-Header, der alles included, geht irgendwie am Sinn der ganzen Geschichte vorbei und wird später (oder vielleicht jetzt schon?) höchstwahrscheinlich zu Problemen führen.

    Ok. Wie macht man es statt dessen? Ich meine, ich habe jetzt schon 20 Headerdateien. Ich will das nicht alles im Main stehen haben.

    Müsstest du das denn? Braucht die main alle 20? Falls ja, dann ist das eben so. Falls nein, dann binde die nicht benötigten doch auch nicht ein!

    Bist du sicher, dass du das Konzept mit den Headern und Übersetzungseinheiten richtig verstanden hast?



  • SeppJ schrieb:

    Müsstest du das denn? Braucht die main alle 20? Falls ja, dann ist das eben so. Falls nein, dann binde die nicht benötigten doch auch nicht ein!

    Bist du sicher, dass du das Konzept mit den Headern und Übersetzungseinheiten richtig verstanden hast?

    Scheinbar habe ich das nicht. Also, das Programm hat jetzt schon etwa 300 Unterfunktionen. Und es werden noch viele werden. Ich arbeite daran seit ungefähr 2.5 Jahren. Ich möchte nicht alles in eine Datei schreiben.
    Ich habe die Funktionen jetzt in unterschiedliche Headerfiles gelegt, wobei sie thematisch unterteilt sind.

    Jetzt, wo das Program sequentiell läuft (ich habe eigentlich die Headerfiles nur übernommen), möchte ich es als DLL rausschreiben und in C# einbinden. Bei einigen Funktionen hat das schon geklappt. Ich nehme exportiere eine Funktion nach der anderen bzw. nehme eine Funktion nach der anderen in das Projekt mit auf.



  • ...funktioniert und ich habe etwas gelernt. Die #includings einfach richtig ordnen, dann genügt es sie nur einmal einzubinden... und das nach drei Jahren C Programmieren 🙂


  • Mod

    CJens schrieb:

    ...funktioniert und ich habe etwas gelernt. Die #includings einfach richtig ordnen, dann genügt es sie nur einmal einzubinden... und das nach drei Jahren C Programmieren 🙂

    Ich muss sagen, das ist schon irgendwie erstaunlich, dass du das nach mehreren Jahren nicht wusstest. Und mehr noch, dass du bisher keine Probleme damit hattest, denn die beschriebenen Fehler machen zwar viele Anfänger, aber es funktioniert halt nicht und sie lernen sofort, wie es richtig geht. Ich bin mir auch ziemlich sicher, dass du selbst jetzt noch nicht das (wichtige!) Konzept der Übersetzungseinheiten verstanden hast. Wie hast du denn C* gelernt? Das klingt nach einem Fall für ein gutes Lehrbuch. Und viel Arbeit, weil du wahrscheinlich in so vielen Jahren dir ziemlich viel schlechte Praktiken angewöhnt hast, die du dir nun selber austreiben musst.

    *: Oder ist es C++? Das ist ein Unterschied! Es sieht zwar aus wie C, aber du hast ja sicher einen Grund, im C++-Forum zu fragen. Genauer gesagt sieht es aus wie C, welches fälschlicherweise mit einem C++-Compiler übersetzt wurde, weil mit einem C-Compiler des export "C" (die einzige Zeile C++ indeinem Programm) sowohl nicht funktionieren würde, als auch gar nicht nötig wäre.



  • Also, ich habe C ein Semester im Studium gelernt - also, nur Basics. Dann habe ich weiter gemacht. Meines Wissens, werden Headerdateien vor dem Kompilieren in den Source Code kopiert. Und dass die nicht doppelt kopiert werden, mache ich eben immer diese Guards.

    Naja, man kommt ziemlich lange damit klar, solange man immer nur das Gleiche macht. Ich mache in C (kein ++ (noch nicht)) reines Number Curnching - große Gleichungssysteme möglichst schnell lösen. Dadurch bin ich recht sicher mit Zeigern, aber mit vielem anderen eben nicht - man trainiert eben immer nur das, was man auch nutzt.
    Das Programm läuft ja sequenziell schon. Und Probleme hatte ich oft - aber ich halt hartnäckig 😉 - neugierig wäre vielleicht besser gewesen.

    Ich versuche reines C zu programmieren. Aber ich kompiliere mit VC++2012. Und ich möchte das Programm in C# ausführen und von dort aus dann auf die Ergebnisse zugreifen (was auch wirklich gut funktioniert). Man kann sogar Zeiger auf ganze Structs an C Sharp übergeben und dort dann weiter auf den Speicher der C Bibliothek zugreifen.



  • CJens schrieb:

    Ich versuche reines C zu programmieren. Aber ich kompiliere mit VC++2012. [...]

    Wieso "aber"? Sag dem Compiler, daß er den Code als C-Code kompilieren soll!


Anmelden zum Antworten