Seite 1 von 1

Visual C++ 8.0 - dllexport statischen Attributs schlägt fehl

Verfasst: 18.01.2010, 21:40
von Eisflamme
Hi,

Ich habe ein Projekt A und ein Projekt B. A ist eine EXE und B eine DLL-Anwendung. Ich möchte Header und Quellcode von B in A verwenden. Alles nicht weiter dramatisch:

Code: Alles auswählen

#ifndef VARIABLEMAPPER_
#define VARIABLEMAPPER_

#include <map>
#include <string>

using namespace std;

namespace KRechner
{
	class __declspec(dllexport) VariableMapper
	{
	public:
		static VariableMapper	instance_;

		map<string, string> variableMap_;
	};
};

#endif
und die Quellcodedatei:

Code: Alles auswählen

#include "Test.hpp"

namespace KRechner
{
	VariableMapper	VariableMapper::instance_;
};
Das liefert halt ein nicht aufgelöstes externes Symbol für instance_:

Code: Alles auswählen

Test.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: static class KRechner::VariableMapper KRechner::VariableMapper::instance_" (?instance_@VariableMapper@KRechner@@2V12@A)".
1>C:\Users\Mischa\Documents\Visual Studio 2008\Projects\SDL OGL\Debug\DLLTest.exe : fatal error LNK1120: 1 nicht aufgelöste externe Verweise.
Der Clou ist: Wenn ich die Zeile map<string, string> variableMap_; aus dem Header entferne, funktioniert es. :(

Ideen?

Viele Grüße

Re: Visual C++ 8.0 - dllexport statischen Attributs schlägt

Verfasst: 19.01.2010, 00:00
von exploid
...

Re: Visual C++ 8.0 - dllexport statischen Attributs schlägt fehl

Verfasst: 19.01.2010, 02:06
von Aramis
Ich gehe mal davon aus, dass du die zu deiner DLL gehörende *.lib im Hauptprogramm natürlich als Abhängigkeit drin hast.

Du hast deine Klasse als dllexport deklariert, der Export sollte also klappen. Der Import aber leider nicht, denn der arme Linker, der deine EXE erstellen muss, hat ja keine Ahnung dass er nach dem Sybol wasweißichwo suchen muss. Üblich ist folgende Lösung:

Code: Alles auswählen

#ifdef MY_DLL_BUILD
#define MY_FRAMEWORK __declspec(dllexport)
#else
#define MY_FRAMEWORK __declspec(dllimport)
#endif

// Für den DLL-Build definierst du MY_DLL_BUILD, der Compiler sieht also das dllexport-Attribut. Andernfalls dllimport.

class MY_FRAMEWORK Foo { .. };
PS: Es gibt eigentlich keinen Grund für dein Hauptprogramm _direkt_ auf dll.VariableMapper.instance_ zuzugreifen. Das ist entgegen jeglicher Kapselung. Wieso machst du nicht einfach einen statischen Accessor draus (das muss das Problem zwar nicht zwingend beseitigen, ist aber wenigstens etwas schöner)?

Re: Visual C++ 8.0 - dllexport statischen Attributs schlägt fehl

Verfasst: 19.01.2010, 08:16
von Eisflamme
Ahhh, super, danke. :) Hat auf Anhieb funktioniert.

Aber wieso funktioniert das bei manchen Klassen auch ohne das dllimport, obwohl ich auch dort die Implementierungen in Quellcodedateien habe und damit publik machen müsste?

Zum Codestil:
Das war nur ein abgespeckter Beispielcode, der den Fehler erzeugen musste. Für möglichst schnellen Zugriff hab ich das Attribut halt kurz public gemacht. Dass ich das so nicht stehen lassen kann, ist natürlich klar. :) Die Klasse ist sonst ein Singleton.

Also vielen Dank! Ich hätte mich im Vorhinein einfach wieder Mal besser informieren sollen *g*

Aber jetzt stellt sich mir ein neues Problem: Ich kann Template-Klassen offensichtlich nicht in eine DLL exportieren. :( Macht ja auch irgendwie Sinn. Aber jetzt fällt die Idee, dass ich verschiedene Programmteile in verschiedene Projekte auslagere, ziemlich, oder? Ich fand die Idee sehr gut, aber wenn ich dafür auf Templates verzichten muss, ist das doch totaler Mist !? :(

Re: Visual C++ 8.0 - dllexport statischen Attributs schlägt fehl

Verfasst: 20.01.2010, 10:27
von dowhilefor
Aber jetzt stellt sich mir ein neues Problem: Ich kann Template-Klassen offensichtlich nicht in eine DLL exportieren. Macht ja auch irgendwie Sinn. Aber jetzt fällt die Idee, dass ich verschiedene Programmteile in verschiedene Projekte auslagere, ziemlich, oder? Ich fand die Idee sehr gut, aber wenn ich dafür auf Templates verzichten muss, ist das doch totaler Mist !?
Naja Templates in DLLs auslagern geht natürlich nicht. Der Kompiler kann ja schlecht erahnen, was jemand mit deiner Template Klasse noch so vor hat. Das ist auch der Grund warum Templates meist komplett im Header stehen(bzw. *.inl) und ich schätze mal die lieferst du doch eh für deine DLL mit, also eigentlich kein Problem :)