View Full Version : [Visual C++] Errore nel linker
Ciao, ho questo pezzo di codice:
std::string config;
std::wstring tmp;
getline(conf_file, config);
tmp=string_wstring(config);
MessageBoxW(NULL, tmp.c_str(), L"Testo", MB_OK);
e string_wstring() è così definita:
std::wstring string_wstring(std::string input)
{
std::wstring output(sizeof(input), L'');
std::copy(input.begin(), input.end(), output.begin());
return output;
}
Ottengo questo errore del linker:
Programma.obj : error LNK2005: "class std::basic_string,class std::allocator > __cdecl string_wstring(class std::basic_string,class std::allocator >)" (?string_wstring@@YA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z) già definito in stdafx.obj
Se tolgo c_str() sparisce l'errore, ma non ho trovato nessuna valida alternativa per poter levare questa funzione.
Da qualche parte avevo letto di forzare il linker a definire più volte la classe, ma vorrei trovare una soluzione migliore. Cosa posso fare?
tomminno
02-03-2010, 19:28
Hai dimenticato qualche #pragma once in testa ad un header?
Comunque per convertire da string a wstring dovresti usare mbstowcs
Hai dimenticato qualche #pragma once in testa ad un header?
No, c'è ._.
Comunque per convertire da string a wstring dovresti usare mbstowcs
What??? O_o
Come funziona?
Mi sono accorto ora che ho bisogno pure della conversione da wstring a string. Questo mbstowcs può sempre essere utile?
tomminno
02-03-2010, 22:34
What??? O_o
Come funziona?
Mi sono accorto ora che ho bisogno pure della conversione da wstring a string. Questo mbstowcs può sempre essere utile?
Da wstring a string c'è wcstombs (wide char to multi byte string). wcstombs e mbstowcs sono funzioni standard C (esistono anche le equivalenti API di Windows che hanno qualche funzionalità in più).
Essendo funzioni C lavorano su array e si usano in 2 fasi, nella prima si richiede la dimensione che dovrà avere il buffer di uscita, e nella seconda viene eseguita la conversione:
string original;
int requiredSize = mbstowcs(NULL, original.c_str(), 0);
char dest[requiredSize];
mbstowcs(dest, original.c_str(), requiredSize);
del tutto analogo il codice per wcstombs.
Da wstring a string c'è wcstombs (wide char to multi byte string). wcstombs e mbstowcs sono funzioni standard C (esistono anche le equivalenti API di Windows che hanno qualche funzionalità in più).
Essendo funzioni C lavorano su array e si usano in 2 fasi, nella prima si richiede la dimensione che dovrà avere il buffer di uscita, e nella seconda viene eseguita la conversione:
string original;
int requiredSize = mbstowcs(NULL, original.c_str(), 0);
char dest[requiredSize];
mbstowcs(dest, original.c_str(), requiredSize);
del tutto analogo il codice per wcstombs.
Beh mi aspettavo qualcosa di più semplice, a questo punto tanto vale che mi tengo le mie funzioni, funzionano e non mi danno problemi.
Piuttosto quello che mi serve è una soluzione per il problema del linker. Idee?
Che orrore :asd:
:banned: Te la potevi risparmiare...
Hai ragione perdonami ma un linguaggio che ha 400 tipi di dato mi fa quest'effetto :p, così come me lo fanno i messaggi del debugger, tipo questo:
error LNK2005: "class std::basic_string,class std::allocator > __cdecl string_wstring(class std::basic_string,class std::allocator >)" (?string_wstring@@YA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z) già definito in stdafx.obj
Neanche fosse C offuscato. Cmq prometto solennemente di non interferire più. Chiedo scusa a tutti.
tomminno
02-03-2010, 23:27
Beh mi aspettavo qualcosa di più semplice, a questo punto tanto vale che mi tengo le mie funzioni, funzionano e non mi danno problemi.
Sei sicuro che funzionino? A me risulta che quella conversione sia errata.
Certo che se le usi per convertire solo caratteri ascii allora torna tutto.
Hai provato con stringhe veramente wide char?
Piuttosto quello che mi serve è una soluzione per il problema del linker. Idee?
header precompilati?
Il fatto che la ritrovi duplicata in stdafx.obj mi fa sospettare di questa opzione.
Sei sicuro che funzionino? A me risulta che quella conversione sia errata.
Certo che se le usi per convertire solo caratteri ascii allora torna tutto.
Hai provato con stringhe veramente wide char?
header precompilati?
Il fatto che la ritrovi duplicata in stdafx.obj mi fa sospettare di questa opzione.
Eh si, ho creato un progetto Win32 con Visual C++ già bello e pronto :rolleyes:
Non mi servono stringhe wide char. Mi serve solo la conversione di testo semplice per poterlo poi passare a MessageBox.
tomminno
03-03-2010, 07:45
Eh si, ho creato un progetto Win32 con Visual C++ già bello e pronto :rolleyes:
Non mi servono stringhe wide char. Mi serve solo la conversione di testo semplice per poterlo poi passare a MessageBox.
Allora vai sulle proprietà del progetto Configuration Properties->General->Character Set e impostalo su Not Set.
Altrimenti puoi usare solo wstring (wcout ecc...) e per le stringhe costanti dichiararle facendole precedere da L
Non funziona ._.
Mi sa tanto che mi tengo i warning...
string original;
int requiredSize = mbstowcs(NULL, original.c_str(), 0);
char dest[requiredSize];
mbstowcs(dest, original.c_str(), requiredSize);
Comunque questo codice non funziona. Non capisco perchè Visual C++ non accetta come dichiarazione della dimensione di un array una variabile O.o vuole per forza un numero :muro:
EDIT: Tra l'altro sempre VS mi dice che è sconsigliato l'uso di mbstowcs e raccomanda invece mbstowcs_s. Ma ho visto che cambiano i parametri della chiamata di funzione...
tomminno
04-03-2010, 14:27
Comunque questo codice non funziona. Non capisco perchè Visual C++ non accetta come dichiarazione della dimensione di un array una variabile O.o vuole per forza un numero :muro:
Si formalmente quello è C99 che non è supportato da VS.
Prova con vector:
string original;
int requiredSize = mbstowcs(NULL, original.c_str(), 0);
vector<wchar_t>dest(requiredSize);
mbstowcs(&dest[0], original.c_str(), requiredSize);
wstring output(dest.begin(), dest.end());
EDIT: Tra l'altro sempre VS mi dice che è sconsigliato l'uso di mbstowcs e raccomanda invece mbstowcs_s. Ma ho visto che cambiano i parametri della chiamata di funzione...
Si dovresti definire _CRT_SECURE_NO_WARNINGS, quasi tutte le funzioni C praticamente sono state marcate come non sicure per via di possibili buffer overflow e ne hanno fatto la versione "sicura" *_s
Ah quindi dici che si possono ancora usare le funzioni "deprecated"?
Nel frattempo avevo usato un modo alternativo che usava la funzione raccomandata, ma c'era sempre quel problema della dichiarazione di array. Nel mio programma molto spesso ricevevo uno stack overflow per via della dimensione troppo piccola dell'array creato.
Questo è il codice:
std::wstring string_wstring(std::string input)
{
size_t origsize = strlen(input.c_str())+1;
const size_t newsize = 10000;
size_t convertedChars = 0;
wchar_t output[newsize];
mbstowcs_s(&convertedChars, output, origsize, input.c_str(), _TRUNCATE);
return output;
}
std::string wstring_string(std::wstring input)
{
const size_t newsize = 10000;
size_t convertedChars = 0;
char output[newsize];
wcstombs_s(&convertedChars, output, origsize, input.c_str(), _TRUNCATE);
return output;
}
_CRT_SECURE_NO_WARNINGS come si definisce? Semplicemente con un #define _CRT_SECURE_NO_WARNINGS?
EDIT: Non mi riconosce il comando vector...
tomminno
04-03-2010, 19:00
_CRT_SECURE_NO_WARNINGS come si definisce? Semplicemente con un #define _CRT_SECURE_NO_WARNINGS?
Si ma più comodamente lo puoi definire tra le proprietà del progetto, così viene definito globalmente per tutti i file del progetto.
EDIT: Non mi riconosce il comando vector...
#include <vector>
e
using namespace std;
o
std::vector
:muro: :muro: :muro: :muro:
Quanto mi mandano in bestia gli errori sui tipi di variabili!!!!!
Con vector non funziona perchè mbstowcs_s vuole un wchar_t* mentre vede in ingresso un std::vector<_Ty>.
Mi sa che mi tengo la soluzione del copy(), è la più semplice.
tomminno
05-03-2010, 12:14
:muro: :muro: :muro: :muro:
Quanto mi mandano in bestia gli errori sui tipi di variabili!!!!!
Con vector non funziona perchè mbstowcs_s vuole un wchar_t* mentre vede in ingresso un std::vector<_Ty>.
Mi sa che mi tengo la soluzione del copy(), è la più semplice.
Come glielo hai passato il vector?
Devi passare l'indirizzo del primo elemento: &dest[0]
La soluzione copy è sbagliata. E comunque se non ti servono i caratteri unicode perchè non modifichi le impostazioni del progetto come ti avevo suggerito?
Come glielo hai passato il vector?
Devi passare l'indirizzo del primo elemento: &dest[0]
La soluzione copy è sbagliata. E comunque se non ti servono i caratteri unicode perchè non modifichi le impostazioni del progetto come ti avevo suggerito?Perché ho altre funzioni che mi ritornano delle string quindi ad ogni modo qualche conversione c'è da fare. Ad esempio getline().
Questo è il codice che ho fin'ora:
std::wstring string_wstring(std::string input)
{
size_t origsize = strlen(input.c_str())+1;
size_t convertedChars = 0;
std::vector<wchar_t>output(origsize);
mbstowcs_s(&convertedChars, &output[0], origsize, input.c_str(), _TRUNCATE);
return output;
}
Questa è la risposta:
impossibile convertire il parametro 1 da 'std::vector<_Ty>' a 'std::basic_string<_Elem,_Traits,_Ax>::_Has_debug_it'
tomminno
05-03-2010, 15:39
Perché ho altre funzioni che mi ritornano delle string quindi ad ogni modo qualche conversione c'è da fare. Ad esempio getline().
Si ma se modifichi le impostazioni del progetto non ne hai bisogno.
Questo è il codice che ho fin'ora:
std::wstring string_wstring(std::string input)
{
size_t origsize = strlen(input.c_str())+1;
size_t convertedChars = 0;
std::vector<wchar_t>output(origsize);
mbstowcs_s(&convertedChars, &output[0], origsize, input.c_str(), _TRUNCATE);
return output;
}
Questa è la risposta:
impossibile convertire il parametro 1 da 'std::vector<_Ty>' a 'std::basic_string<_Elem,_Traits,_Ax>::_Has_debug_it'
Scusa ma te stai facendo il return di un vector mentre il metodo dovrebbe ritornare una wstring.
Devi prima costruire la wstring a partire dal vector. L'esempio completo te l'avevo già postato prima.
E poi perchè mai stai usando le funzioni non standard di Microsoft?
Comunque ripeto se cambi le impostazioni di progetto non hai bisogno di questi metodi.
Si ma se modifichi le impostazioni del progetto non ne hai bisogno.
Scusa ma te stai facendo il return di un vector mentre il metodo dovrebbe ritornare una wstring.
Devi prima costruire la wstring a partire dal vector. L'esempio completo te l'avevo già postato prima.
E poi perchè mai stai usando le funzioni non standard di Microsoft?
Comunque ripeto se cambi le impostazioni di progetto non hai bisogno di questi metodi.
Hai ragione, scusa, mi ero scordato di quella riga :doh:
Perché dici funzioni non standard? A dire il vero sto facendo di tutto per mantenermi il più possibile entro i limiti dello standard C++. Ho usato la libreria fstream.
EDIT: Aspetta, cosa intendi per modificare le impostazioni del progetto?
PS. Tra l'altro, non essendo abituato al Visual C++, non riesco a trovare dove poter definire quello che mi avevi detto nelle proprietà del progetto... Dove va messo???
EDIT2:
Ora è perfetta la conversione *_* Prima avevo problemi con alcuni caratteri tipo le lettere accentate, ora non più.
Ecco il codice:
//Converte una variabile da string a wstring
std::wstring string_wstring(std::string input)
{
size_t origsize = strlen(input.c_str())+1;
size_t convertedChars = 0;
std::vector<wchar_t>vec(origsize);
mbstowcs_s(&convertedChars, &vec[0], origsize, input.c_str(), _TRUNCATE);
std::wstring output(vec.begin(), (vec.end()-1));
return output;
}
//Converte una variabile da wstring a string
std::string wstring_string(std::wstring input)
{
size_t origsize = wcslen(input.c_str())+1;
size_t convertedChars = 0;
std::vector<char>vec(origsize);
wcstombs_s(&convertedChars, &vec[0], origsize, input.c_str(), _TRUNCATE);
std::string output(vec.begin(), (vec.end()-1));
return output;
}
L'ultima riga l'ho dovuta modificare perché altrimenti mi ritornava una variabile che aveva alla fine un valore nullo e nelle uguaglianze con testo o altre variabili sbagliava.
tomminno
05-03-2010, 16:19
Hai ragione, scusa, mi ero scordato di quella riga :doh:
Perché dici funzioni non standard? A dire il vero sto facendo di tutto per mantenermi il più possibile entro i limiti dello standard C++. Ho usato la libreria fstream.
Le funzioni *_s sono estensioni microsoft e non fanno parte del C standard.
EDIT: Aspetta, cosa intendi per modificare le impostazioni del progetto?
PS. Tra l'altro, non essendo abituato al Visual C++, non riesco a trovare dove poter definire quello che mi avevi detto nelle proprietà del progetto... Dove va messo???
Scusa ma le leggi le risposte? Come fare te l'ho scritto 2 giorni fa.
Le funzioni *_s sono estensioni microsoft e non fanno parte del C standard.
Ah non l'avevo capito. Uhm deprecated vs. non standard...
Scusa ma le leggi le risposte? Come fare te l'ho scritto 2 giorni fa.
Allora vai sulle proprietà del progetto Configuration Properties->General->Character Set e impostalo su Not Set.
Intendi questo? Se tolgo UNICODE il compilatore mi tira fuori 11 errori...
tomminno
05-03-2010, 16:38
Intendi questo? Se tolgo UNICODE il compilatore mi tira fuori 11 errori...
Perchè stai usando direttamente le funzioni di windows con W?
Se imposti Not Set non hai bisogno di nessuna funzione di conversione, sempre che non ti interessi scrivere testi giapponesi, nel qual caso dovresti lasciare Unicode.
Ti basta correggere gli altri errori.
Perchè stai usando direttamente le funzioni di windows con W?
Se imposti Not Set non hai bisogno di nessuna funzione di conversione, sempre che non ti interessi scrivere testi giapponesi, nel qual caso dovresti lasciare Unicode.
Ti basta correggere gli altri errori.
Ah giusto, infatti gli errori sono tutti sulla conversione.
Ma a questo punto, dato che ormai in unicode mi funziona bene, mi conviene togliere la codifica?
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.