Statische Lib - Problem

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
X0r
Beiträge: 2770
Registriert: 15.03.2007 21:47
Kontaktdaten:

Statische Lib - Problem

Beitrag von X0r »

Ich versuche hier gerade eine statische Lib in VC++ zu erstellen und sie in PB über Import zu benutzen. Die meisten "unresolved external symbol" Fehler habe ich dabei beseitigen können. Allerdings komme ich hier einfach nicht weiter:
POLINK: error: Unresolved external symbol '_vsnprintf_s'.
Was genau fehlt denn da noch?
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Statische Lib - Problem

Beitrag von Danilo »

X0r hat geschrieben:
POLINK: error: Unresolved external symbol '_vsnprintf_s'.
Was genau fehlt denn da noch?
Ein Hinweis auf die msvcr100.dll oder msvcr90.dll oder msvcr80.dll, je nachdem
welche Version Du verwendest.
Die dazugehörige Import-Lib bei MSVC++ ist msvcrt.lib. Dann musst Du aber
die DLL mit ausliefern. Flag für VC++ ist /MD.
Noch ein Hinweis aus MSDN dazu:
"Be aware that if you use the Standard C++ Library, your program will
need MSVCP100.DLL to run." (Gilt für VS++2010, bei älteren Versionen
dann wohl entsprechend MSVCP90.DLL oder MSVCP80.DLL)

PureBasics msvcrt.lib hat diese Funktion scheinbar nicht, ist wohl
wieder zu alt.

Die statische Version ist bei MSVC++ in libcmt.lib, dann brauchst Du die DLL nicht.
Flag für VC++ ist /MT.
Ob Du die libcmt.lib lizenzrechtlich einfach von VC++ nehmen darfst und Deiner
Library hinzufügen kannst? Normal darf man nur die redistributable DLLs weitergeben.
Oder es wird beim kompilieren mit /MT automatisch eingefügt?
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
X0r
Beiträge: 2770
Registriert: 15.03.2007 21:47
Kontaktdaten:

Re: Statische Lib - Problem

Beitrag von X0r »

PureBasics msvcrt.lib hat diese Funktion scheinbar nicht, ist wohl
wieder zu alt.
Jup, hatte ich zu Beginn auch ausprobiert.
Die statische Version ist bei MSVC++ in libcmt.lib, dann brauchst Du die DLL nicht.
Flag für VC++ ist /MT.
Ob Du die libcmt.lib lizenzrechtlich einfach von VC++ nehmen darfst und Deiner
Library hinzufügen kannst? Normal darf man nur die redistributable DLLs weitergeben.
Oder es wird beim kompilieren mit /MT automatisch eingefügt?
Bitte verzeih mir, wenn ich jetzt etwas falschen von mir gebe. Bin kein Experte in diesem Gebiet. Aber was bringt mir das, wenn ich diese Lib in PureBasic verwenden will? Jedenfalls hatte ich die Option /MT schon die ganze Zeit an. Scheint wohl nichts zu bringen dagegen statisch zu linken.

Was jetzt aber geklappt hat: die in VC++ 2010 Express beigelieferte msvcrt.lib über Import in PB einbinden.

Gäbe es da noch andere passable Vorschläge
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Statische Lib - Problem

Beitrag von Danilo »

X0r hat geschrieben:Bitte verzeih mir, wenn ich jetzt etwas falschen von mir gebe. Bin kein Experte in diesem Gebiet. Aber was bringt mir das, wenn ich diese Lib in PureBasic verwenden will? Jedenfalls hatte ich die Option /MT schon die ganze Zeit an. Scheint wohl nichts zu bringen dagegen statisch zu linken.
Du kompilierst ja mit VC++ nur, wobei ein Verweis auf _vsnprintf_s
zu Deiner Lib hinzugefügt wird. Das linken passiert dann erst bei PureBasic
durch PoLink, und der findet die Funktion nur, wenn Du libcmt.lib zu Deiner
Library hinzufügst (in etwa: "lib /OUT:final.lib your.lib libcmt.lib"), was halt
eventuell lizenzrechtlich fragwürdig ist, da die libcmt.lib Code von Microsoft enthält.

EDIT: Das war darauf bezogen, wenn Du die Lib veröffentlichen willst.
Vielleicht machst Du das ja auch nur für Dich (Torque3D?).
Deshalb meinte ich auch "lib /OUT:final.lib your.lib libcmt.lib" wenn Du
das als UserLib machst, sonst kannst Du diese Lib ja auch per Import
rein holen. Ist die libcmt.lib bei VC++Express dabei?
X0r hat geschrieben:Was jetzt aber geklappt hat: die in VC++ 2010 Express beigelieferte msvcrt.lib über Import in PB einbinden.
So hast Du wieder eine Abhängigkeit zu einer msvcrXXX.dll. Das ist ja kein
Problem, denn die redistributable DLLs darfst Du ja verteilen, nur bin ich nicht
sicher ob Du das willst. PureBasic'ler mögen ja meist standalone apps. ;)

Es gibt natürlich auch noch die Möglichkeit, daß Du "_vsnprintf_s" selbst
schreibst, wenn zum linken eh nur diese eine Funktion fehlt.
Bitte nicht schlagen, wenn ich jetzt was falsches gesagt habe...
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
X0r
Beiträge: 2770
Registriert: 15.03.2007 21:47
Kontaktdaten:

Re: Statische Lib - Problem

Beitrag von X0r »

EDIT: Das war darauf bezogen, wenn Du die Lib veröffentlichen willst.
Vielleicht machst Du das ja auch nur für Dich (Torque3D?).
Deshalb meinte ich auch "lib /OUT:final.lib your.lib libcmt.lib" wenn Du
das als UserLib machst, sonst kannst Du diese Lib ja auch per Import
rein holen. Ist die libcmt.lib bei VC++Express dabei?
:mrgreen: , Torque hab ich mir noch nicht geholt. Es geht aber um eine andere hochinteressante Lib.

Die libcmt.lib hab ich mal importiert, dann ergibt sich aber folgende Fehlermeldung:
POLINK: error: Unresolved external symbol '_main'.
Eine Abhängigkeit zu irgendwelchen DLLs wäre unschön.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Statische Lib - Problem

Beitrag von Danilo »

X0r hat geschrieben:Die libcmt.lib hab ich mal importiert, dann ergibt sich aber folgende Fehlermeldung:
POLINK: error: Unresolved external symbol '_main'.
Vielleicht kannst Du damit was anfangen:

Code: Alles auswählen

!public _main
!public _wmain
!public _wWinMain
!public _WinMain

ImportC "libcmt.lib"
   isalpha.l(c.l)
   
   ;WinMainCRTStartup()
   mainCRTStartup()
   ;wWinMainCRTStartup()
   wmainCRTStartup()
EndImport


CompilerIf #PB_Compiler_Unicode=0
  mainCRTStartup()    ; initialisiere die C runtime library
CompilerElse
  wmainCRTStartup()
CompilerEndIf
!Call _PB_EOP_NoValue
!ret

;
; diese Labels werden von der C runtime init function aufgerufen
;
!_wWinMain:
!_WinMain:
!_main:
!_wmain:
  Gosub Start
!ret



;
; hier Dein code
;
Start:
    If OpenConsole()
       PrintN("cool")
       PrintN( Str( isalpha('a') ) )
       PrintN( Str( isalpha('1') ) )
       PrintN("cool")
    
       Input()
       CloseConsole()
    EndIf
Return
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
X0r
Beiträge: 2770
Registriert: 15.03.2007 21:47
Kontaktdaten:

Re: Statische Lib - Problem

Beitrag von X0r »

Hm,
ich denke ich werds wohl über ne DLL lösen.

Dennoch vielen Dank für deine Hilfe!

Hab dir mal ne PN geschickt, eventuell kommst du ja weiter als ich.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Statische Lib - Problem

Beitrag von Danilo »

X0r hat geschrieben:Hm, ich denke ich werds wohl über ne DLL lösen.
Auch wenn Du die DLL-Version der VC++ Runtime nimmst,
mußt Du diese initialisieren, sonst kann es laut MSDN zu
einem "C Run-Time Error R6030" kommen:
MSDN hat geschrieben:CRT not initialized

This error occurs if you are using the CRT, but the CRT startup code was not executed. It is possible to get this error if the linker switch /ENTRY is used to override the default starting address, usually mainCRTStartup, wmainCRTStartup for a console EXE, WinMainCRTStartup or wWinMainCRTStartup for a Windows EXE, or _DllMainCRTStartup for a DLL.
Der obige Code war eh nicht korrekt und hätte nur Probleme gemacht. :)

Hier die neue Version:

Code: Alles auswählen

#PB_Compiler_Console = 0  ; set to 1 if you compile as console app

#USE_STATIC_C_LIBRARY = 1 ; 1 = static  c library
                          ; 0 = dynamic c library (DLL)

;>[ VC++ library include ]--------------------------------------------
CompilerIf #PB_Compiler_OS = #PB_OS_Windows

    CompilerIf #PB_Compiler_Debugger
        CompilerError "Important: Disable debugger!"
    CompilerEndIf

    ;>[ VC++ library import ]-----------------------------------------
    CompilerSelect #PB_Compiler_Processor
        CompilerCase #PB_Processor_x86
            CompilerIf #USE_STATIC_C_LIBRARY = 0
                ImportC "msvcrt.lib"          ; msvcrt.lib   = 32bit dynamic VC++ runtime library
            CompilerElse
                ImportC "libcmt.lib"          ; libcmt.lib   = 32bit static  VC++ runtime library
            CompilerEndIf
        CompilerCase #PB_Processor_x64
            CompilerIf #USE_STATIC_C_LIBRARY = 0
                ImportC "msvcrt64.lib"        ; msvcrt64.lib = 64bit dynamic VC++ runtime library (rename it)
            CompilerElse
                ImportC "libcmt64.lib"        ; libcmt64.lib = 64bit static  VC++ runtime library (rename it)
            CompilerEndIf
    CompilerEndSelect
            isalpha.l(c.l)

            WinMainCRTStartup()  ; Windows
            mainCRTStartup()     ; Console
            wWinMainCRTStartup() ; Windows, Unicode
            wmainCRTStartup()    ; Console, Unicode
        
            DllMainCRTStartup()  ; call this to init the C library in DLLs
    EndImport

    
    ;>[ VC++ library init ]-------------------------------------------
    CompilerIf #PB_Compiler_Unicode=0
        CompilerIf #PB_Compiler_Console = 0
            WinMainCRTStartup()  ; init VC++ runtime library, Windows
        CompilerElse
            mainCRTStartup()     ; init VC++ runtime library, Console
        CompilerEndIf
    CompilerElse
        CompilerIf #PB_Compiler_Console = 0
            wWinMainCRTStartup() ; init VC++ runtime library, Windows, Unicode
        CompilerElse
            wmainCRTStartup()    ; init VC++ runtime library, Console, Unicode
        CompilerEndIf
    CompilerEndIf
            !ret
    
    CompilerSelect #PB_Compiler_Processor
        CompilerCase #PB_Processor_x86
            !public _main
            !public _wmain
            !public _wWinMain
            !public _WinMain
            !_main:
            !_wmain:
            !_wWinMain:
            !_WinMain:
        CompilerCase #PB_Processor_x64
            !public main
            !public wmain
            !public wWinMain
            !public WinMain
            !main:
            !wmain:
            !wWinMain:
            !WinMain:
    CompilerEndSelect    
CompilerElse
  CompilerError "Error. VC++ library only supported on windows."
CompilerEndIf
;>[ VC++ library end ]------------------------------------------------
;
;-[ Main ]------------------------------------------------------------
;
; start of program
;
EnableExplicit


Procedure output()
   Define i
   For i = 0 To 255
     Print( Str( isalpha(i) ) )
   Next
   PrintN("")
EndProcedure


If OpenConsole()
   PrintN("output start")
   output()
   PrintN("output end")
   PrintN("press <ENTER>")
   Input()
   CloseConsole()
EndIf
Du kannst zwischen der statischen und dynamischen (DLL) Version
mit der Konstante #USE_STATIC_C_LIBRARY wählen.

Unterstützt werden 32bit und 64bit Versionen der Libraries, allerdings
mußt Du die 64bit-Versionen umbenennen zu msvcrt64.lib & libcmt64.lib.

Beim kompilieren mit Unicode wird die Unicode-Version der
Initialisierungsfunktion aus der VC++ Library gewählt.

Wenn Du als Console-Programm kompilierst, muß die Konstante
#PB_Compiler_Console ganz am Anfang auf 1 gesetzt werden,
wenn Du als Windows-Programm kompilierst eben auf 0.
Für die DLL-Erstellung funktioniert dieser Code nicht, dafür muß
man über DllMainCRTStartup() wieder ganz anders rangehen.

Weiterhin ist sehr wichtig, daß der Startup-Code zum initialisieren
genau so dort bleibt und eigener PB-Code erst nach dem Marker
";-[ Main ]---------------------------------------------------------"
anfängt. Ab dort kannst Du dann aber ganz normal coden.

Durch das einbinden und initalisieren der VC++ Runtime Library
wird der Programmablauf geändert:
  • 1. PB initialisiert libraries usw. in ASM
  • 2. Die VC++ Runtime wird initialisiert.
  • 3. Die VC++ Runtime springt eines der verschiedenen "main" Labels an
  • 4. Der normale PB Code wird ausgeführt
  • 5. PB räumt auf in ASM (library end functions usw.)
  • 6. PB springt zurück in die VC++ Runtime Init Function
  • 7. Die VC++ Runtime räumt auf
  • 8. Das Programm wird beendet
Probier nochmal damit. Die VC++ Runtime Library wird so schön
in allen möglichen Variationen eingebunden (x86,x64,Unicode,statisch,dynamisch).

Daran sollte es imo nicht liegen, wenn Du noch Fehler bekommst.

EDIT: Debugger muß aus sein! Der mag das wohl nicht,
wenn der Programmablauf geändert wird (verständlich). :)
'DisableDebugger' hilft da auch nicht.
Zuletzt geändert von Danilo am 03.05.2011 09:54, insgesamt 4-mal geändert.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
DrShrek
Beiträge: 1970
Registriert: 08.09.2004 00:59

Re: Statische Lib - Problem

Beitrag von DrShrek »

X0r hat geschrieben: Torque hab ich mir noch nicht geholt. Es geht aber um eine andere hochinteressante Lib.
Vieleicht kann Dir besser geholfen werden, wenn klar ist was für eine hochinteressante Lib Du meinst?
Siehste! Geht doch....?!
PB*, *4PB, PetriDish, Movie2Image, PictureManager, TrainYourBrain, ...
Benutzeravatar
inc.
Beiträge: 348
Registriert: 27.10.2004 12:25

Re: Statische Lib - Problem

Beitrag von inc. »

@ Danilo

Genial!
Seit VS 2005 gab es das Problem mit Manifest und Co. bei dynamischen linken mit der MSCRT von VS resultierenden libs!
Ich hatte daher immer mit dem kostenlosen VisualC++2003 bzw. GCC und Code::blocks für beide Compiler als IDE jene C/C++ Sourcen kompiliert um die o.g. Probleme zu umgehen. Vorteil war immer, ich konnte später in PB mit der PB mitgelieferten msvcrt linken.

Aber das Herangehen von Dir oben sieht vielversprechender aus.


Danke.
Hier gibts die OOP Option für PureBasic.
Antworten