C++ WinMain() in statisch gelinkter Lib

cplusplus

Cadet 1st Year
Registriert
März 2008
Beiträge
15
Hallo,

ich würde gerne den User Entry Point WinMain() in einer statisch gelinkten Bibliothek unterbringen. Vom Linker bekomme ich aber folgende Fehlermeldung:

Code:
MSVCRTD.lib(crtexew.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_WinMain@16" in Funktion "___tmainCRTStartup".

Die Lib ist aber sicher in dem Linkeraufruf, das Symbol der WinMain() wird aber wahrscheinlich zu früh rausgeworfen, weil es nicht referenziert wird (die CRT lib kommt in der Befehlszeile im VS nicht vor, eventuell wird die erst später dazugelinkt?).

Ist es möglich dem VS 2008 den Linkeraufruf so beizubringen, dass mein WinMain Symbol bis zum Linken mit der CRT Lib überlebt?

Viele Grüße
Daniel
 
da fallen mir spontan eigentlich nur 2 fehler ein:
1) die statische library mit WinMain wird nicht korrekt beim finalen linken mit angegeben
2) deine WinMain hat eine falsche signatur.
 
Wie kann ich denn mit der M$ Entwicklungsumgebung die Symbole meiner Lib auflisten?

EDIT: Ich kann eigentlich beides mit ziehmlicher Sicherheit ausschließen, da es wunderbar funktioniert, wenn ich die WinMain per Copy&Paste ins Hauptprojekt einfüge. Auch benutzt das Hauptprojekt weitere Klassen dieser Lib.

EDIT2: Das Problem gleicht meinem wie die Faust aufs Auge: http://www.gamedev.net/community/forums/topic.asp?topic_id=451727
 
Zuletzt bearbeitet:
Da du von Klassen sprichst, nehme ich mal an, du hast C++ Quellcode und kompilierst entsprechend. WinMain ist jedoch eine C Funktion und erfordert auch eine C Signatur. Das erreichst du mittels extern "C".
Code:
extern "C" int WINAPI WinMain(...)
 
Jup hab ich. Wie gesagt muss es eigentlich ein Fehler beim Linken sein, da ich keine Fehler erhalte, wenn ich die WinMain per Copy&Paste ins Hauptprojekt einfüge.

Am besten ich erstelle heute Abend mal ein kleines Test Solution, welches das Problem verdeutlicht.

EDIT: Der Link in meinem vorigen Posting bezieht sich auf exakt das selbe Problem (allerdings ohne eine Lösung). Ich verfolge auch den Ansatz die WinMain in eine statische Lib zu packen und den eigentlichen Anwendungscode über ein Singleton anzustoßen. Das ganze hat zum Zweck im "Hauptcode" plattformunabhängig zu sein und alles plattformspezifische zu kapseln.
 
Zuletzt bearbeitet:
cplusplus schrieb:
Am besten ich erstelle heute Abend mal ein kleines Test Solution, welches das Problem verdeutlicht.
Yep, mach das mal. Ich habe ein Minimalbeispiel getestet, funktioniert problemlos.

cplusplus schrieb:
Wie kann ich denn mit der M$ Entwicklungsumgebung die Symbole meiner Lib auflisten?
Ob die IDE etwas anbietet, kann ich dir momentan nicht sagen. Aber es gibt ein Kommandozeilen Tool zum Compiler, dumpbin, damit kannst du dir die Symbole auflisten.

Übrigens, vergiss was ich oben geschrieben habe. Egal ob extern "C" oder nicht, der MS Compiler scheint bei der Funktion immer C Name Mangling zu verwenden, egal ob C oder C++ Kompilat.
 
Hier ein schnell zusammengehacktes Minimalbeispiel, welches bei mir nicht linken will. Erstellt wurde es mit Visual Studio 2008 Professional Edition.

EDIT: Wenn ich den Entry Point manuell setze (Linker: Erweitert: Einstiegspunkt: (w)WinMainCRTStartup), dann funktioniert es. Komischerweise funktioniert es auch, wenn ich Unicode abschalte (Zeichensatz: Multi-Byte-Zeichensatz verwenden) und vor der WinMain noch tchar.h einbinde, ohne den Entry Point selbst zu definieren. Warum muss ich eigentlich den Entry Point manuell setzen, wenn VS das von dem Unicode Setting ableiten könnte?
 

Anhänge

Zuletzt bearbeitet:
Es scheint tatsächlich so zu sein, dass du keine andere Möglichkeit hast, als den Entry Point explizit anzugeben. Schau mal hier. Ist zwar MFC, aber praktisch das gleiche Problem. Naja, halt "behavior by design". :)

Andererseits, schon mal darüber nachgedacht, in deiner Lib generell nur WinMain zu verwenden, anstatt _tWinMain, welches für Unicode zu wWinMain aufgelöst wird? Bis auf den Parameter lpCmdLine ändert sich für dich dadurch ja erstmal nichts. Und die Kommandozeile kann man auch mittels GetCommandLine abfragen, falls man eine Unicode Zeichenkette benötigt. So besteht zumindest keine Notwendigkeit für den Nutzer deiner Lib, den Entry Point uU neu definieren zu müssen.
 
Die Idee mit WinMain in Kombination mit GetCommandLine gefällt mir. Vielen Dank für eure Hilfe!
 
Die Signatur von WinMain ist folgende:
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
);

wenn du diese in deiner library benutzt, dann funktioniert auch das linken!
 
Nun es gibt auch einen Unicode User Entry Point:
Code:
int WINAPI [COLOR="Red"]wWinMain[/COLOR](
  HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  [COLOR="Red"]LPWSTR[/COLOR] lpCmdLine,
  int nCmdShow
);

Durch die Verwendung von typedefs aus tchar.h kann man je nach Einstellung des Compilers den passenden Einstieg verwenden:
Code:
int WINAPI [COLOR="Red"]_tWinMain[/COLOR](
  HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  [COLOR="Red"]LPTSTR[/COLOR] lpCmdLine,
  int nCmdShow
);

Dummerweise nimmt der M$ Compiler (keine Ahnung wie es bei den anderen aussieht) den Entry Point nicht abhängig von der Unicode Einstellung, man muss zusätzlich den Einsprungpunkt auf wWinMainCRTStartup ändern, welches dann den User Entry Point wWinMain aufruft. Der vorgeschlagene Workaround, bei dem ich den Einsprungpunkt nicht extra für Unicode und Multi-Byte anpassen muss, ist folgender:
Code:
int WINAPI WinMain(
  HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  LPSTR,
  int nCmdShow
)
{
  LPTSTR lpCmdLine = GetCommandLine();

  ...
}

In beiden Fällen stehen damit die Parameter von WinMain bzw. wWinMain zur Verfügung, aber der Einsprungpunkt bleibt der selbe.
 
Zurück
Oben