Funktion zur typsicheren Eingabe in dll
-
Hallo,
ich habe gerade eine Funktion geschireben die mir sozusagen eine "sichere" Eingabe ermölicht, d.h. dass zB in eine int-Variable nicht versehentlich ein buchstabe eingeben wird;die Funktion habe ich in eine dll kopiert, dort ist sie so derkleriert:
template<class T> __declspec(dllexport) void safe_cin(T& Zielvariable) { do { cin>>Zielvariable; if(cin.fail()) { cin.clear(); //fail-state vergessen cin.ignore(); //Zeichen im Stream vergessen cout<<"Fehleingabe, bitt erneut eingeben!\n"; } } while(cin.fail()); }in die main.cpp meiner Konsolenanwendung importiere ich sie so:
template<class T> __declspec(dllimport) void safe_cin(T& Zielvariable);edit:
nur sobald ich sie in main aufrufe gibt der compiler verschiedenen meldungen aus;rufe ich sie zB so auf:
int a; safe_cin(a);gibt der Compiler eine Fehlermeldung aus:
Microsoft Visual C++ 2008 Express Edition schrieb:
Verweis auf nicht aufgelöstes externes Symbol ""__declspec(dllimport) void __cdecl safe_cin<int>(int &)" (__imp_??$safe_cin@H@@YAXAAH@Z)" in Funktion "_main".
1 nicht aufgelöste externe Verweiserufe ich sie so auf:
int a; safe_cin(&a);sagt der compiler:
Microsoft Visual C++ 2008 Express Edition schrieb:
safe_cin': Konvertierung des Parameters 1 von 'int *' in 'int *&' nicht möglich
und rufe ich sie so auf:
int a; safe_cin(*a);sagt der compiler:
Microsoft Visual C++ 2008 Express Edition schrieb:
error C2100: Ungültige Dereferenzierung.
wie muss ich diese funktion also korrekt aufrufen?
danke schonmal,
andi01.BTW: wenn ich die funktion in main.cpp dekleriere funktioniert alles mit dem aufruf
int a; safe_cin(a);perfekt;
-
Du musst auch die Lib-Datei, die zusammen mit der Dll erstellt wurde, linken. Anscheinend tust du das nicht, da der Linker einen unaufgelösten Verweis zu beanstanden hat. (Siehe erste Fehlermeldung)
MfG, Jochen
-
Und wie soll das bitte funktionieren? Der Compiler macht aus dem Template erst Objektcode, wenn eine bestimmte Instanz dieses Templates erstellt wurde (z.B. für
int). Wenn du die DLL kompilierst wird dort folglich die Funktion nicht als Objektcode vorliegen, da du die Funktion nirgendwo aufrufst. Wenn du es dann irgendwann in der Anwendung machen willst, gibt er dir trotzdem einen Linkererror, auch wenn du die Lib gelinkt hast.
-
Jochen S. schrieb:
Du musst auch die Lib-Datei, die zusammen mit der Dll erstellt wurde, linken. Anscheinend tust du das nicht, da der Linker einen unaufgelösten Verweis zu beanstanden hat. (Siehe erste Fehlermeldung)
Doch, die habe ich mitgelinkt
das sieht man zB daran dass der compiler alle anderen funktionen in derselben dll auch findet und sie perfekt funktionieren.@Ad aCTa :
wie kann ich es dann besser machen? ich muss templates verwenden weil die Funktion ja vom einzugebenden Datentypen unabhängig bleiben muss.Ad aCTa schrieb:
[...] da du die Funktion nirgendwo aufrufst
reicht es dann schon wenn irgendeine andere Funktion in der dll safe_cin() aufruft?
also zB so:
template<class T> __declspec(dllexport) void safe_cin(T& Zielvariable) { //inhalt siehe oben } void call_safe_cin() { int a; safe_cin(a); }(die fehlermeldungen kommen übrigens nicht beim kompilieren der dll, das geht fehlerfrei, erst bei der main.cpp der konsolenanwendung beschwert sich der compiler
)mfg,
andi01.
-
Achso, das mit dem Objektcode wusste ich jetzt nicht, Ich hab noch nie versucht, Template-Funktionen in Dll-Dateien auszulagern. Zur Lösung des Problems würden mir jetzt nur zwei Wege einfallen:
1. Du definierst die Template-Funktionen in einer Headerdatei (oder in main.cpp)
2. Man könnte die Funktion für jeden Datentyp überladen, mit denen ein Funktionsaufruf Sinn macht.MfG, Jochen
-
Das kann nicht gehen.
Der C++ Compiler muss genau alle Typen zur Compilezeit erkennen. In der From wie der OP das gemacht hat, wird in der DLL gar kein Code erzeugt!Wenn muss der Code in der DLL instanziiert werden und dann existieren auch nur die Typen, die an instanziiert hat.
-
Anwendungen und DLLs sind eigenständige Projekte. Eine DLL kann nur das zur Verfügung stellen, wofür sie eingerichtet ist - und die Anwendungen können nur das nutzen, was sie als vorbereitete Leistungen von der DLL geboten bekommen.
Klingt vielleicht etwas kompliziert, ist aber genau so!

Warum prüfst du die typensichere Eingabe nicht direkt in der Anwendung? Dies auf eine DLL zu übertragen ist machbar, erfordert aber klar durchdachten Aufwand. Zielsetzung ist schon gut, führt auf ein Programmier-Utility hinaus. Vielleicht gibt es da bereits etwas fertiges?

Ich mache solche Sachen schon während der Eingabe meist mit 'subclasses' oder lese einfach als String und interpretiere, ob es passt oder nicht.
