Newsgroup: it.comp.programmare.win32
Titolo: Utilizzo di EXTERN

Ciao A tutti
Volevo chiedervi un aiuto per l'utilizzo di extern.
Io ho creato un file Strutture.h in cui ho messo solo le strutture che ho voluto creare come per esempio:
	struct users
	{
	short user;//2 Bytes
	char Password[20];//22
	char NomeUtente[100];//122 bytes
	char free[200-122];//200 BYtes
	};
poi ho creato un file che si chiama extern.h
in cui ho dichiarato
	#include "Strutture.h"
	extern struct users user;
poi nel file nomeprogramma.cpp
ho incluso il file extern.h e ho compliato.
Mi da errore LNK2001 -  simbolo esterno non risolto.
Secondo voi perchč?
Grazie 
Ciao

Secondo voi perchč?
Perche' il link non trova la definizione di "user" da nessuna
parte, tu l'hai specificata solo come extern, cioe' "esterna" al
sorgente nomeprogramma.cpp.
Quindi se hai due file, ad esempio main.cpp e altro.cpp, il primo
dovra' contenere:
	#include "Strutture.h"
	struct users user;
e il secondo:
	#include "Strutture.h"
	extern struct users user;
Nel primo sorgente c'e' la definizione, nel secondo il
riferimento.

riferimento.
Aspetta, se includo Strutture.h anche in questo file, mi dice che le strutture sono già definite in un altro fil OBJ al momento della compilazione e non funziona.
Il file strutture .h lo posso includere solo in un file di tutta la soluzione altrimenti non compila.
Sicuramente avrò sbagliato dall'inizio a fare il file Strutture.h in cui volevo mettere delle strutture che fossero visibili in tutto il programma...

Secondo voi perchč?
Un errore del genere cosi banale denota che sicuramente sei agli inizi
dell'apprendimento.
Consiglio 1 :
postare su un NG adatto che tratti del C,C++
Consiglio 2 :
studiare le basi su un ottimo testo tipo Lippman o Stroustrup 
ciao

compilazione e non funziona.
File Strutture.h ========================
struct users
	{
	short user;//2 Bytes
	char Password[20];//22
	char NomeUtente[100];//122 bytes
	char free[200-122];//200 BYtes
	};
====================================
File altro.cpp =======================
#include "Structure.h"
extern struct users user;
==================================
File main.cpp =====================
#include <stdio.h>
#include "Structure.h"
struct users user;
int main (int argc,char* argv [])
{
printf ("Hello World!\n");
return 0;
}
================================

 Secondo voi perchč?
La keyword "extern" dice al compilatore e al linker: esiste una certa 
variabile "user" che e' di tipo "struct users". Cosi' facendo, tu l'hai 
*dichiarata* (cioe', hai detto "da qualche parte esiste").
La puoi dichiarare quante volte vuoi, ma devi *definirla* *una sola* 
volta. La definizione va posta in un file sorgente .c/.cpp.
Cioe', ad es. in nomeprogramma.cpp (o in qualche altro file .c/.cpp), 
devi scrivere:
	struct users user;
(senza extern)
Effettivamente, questa domanda e' adeguata per un NG di programmazione 
C/C++, non qui ...
Tieni anche conto che mi pare che tu usi il C++ e non il C.
Pertanto, puoi scrivere:
users user;
(senza struct, in quanto per il C++ struct == class con membri public)
Ciao

 ha scritto:
Credo di aver capito!
Grazie mille!




Ciao
Sto studiando le basi su un libro italiano che credo sia di due prof universitari
e quella parte che tratta l'utilizzo di extern non č chiarissima.
Immaginavo che fosse una domanda da NG di C, ma non ne ero sicuro.

C/C++, non qui ...
Vabbè, però non mi pare che parlo di tortellini o di astronomia!
Grazie della spiegazione.
Ho notato cmnq che ci sono meno problemi a trovare risposte su cose più chiare come le sintassi del C
che invece fare domande su cose che riguardano le MFC tipo :
perchè su questa funzione :
void CTabelleDati::OnHdnEndtrackListaTabella(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
	LVCOLUMN *pColumn=new LVCOLUMN;
	pColumn->cx=lCol[phdr->iItem]; // questa è una costante con valore  50
	m_Lista_Tabella.SetColumn(phdr->iItem,pColumn);
	*pResult = 0;
}
La colonna non mi ritorna a 50 e invece prende la larghezza che ho impostato trascinandola?
Ho provato anche con SetColumnWidht e succede lo stesso.
Ciao
F

 }
In questo codice c'e' un errore di C++ *grave*.
Tu alloci pColumn con new LVCOLUMN...ma poi che fine fa quell'oggetto?? 
Non lo deallochi mai, mi pare! Giusto?
Dovresti alloare l'oggetto LVCOLUMN sullo stack, non nello heap, con un 
semplice:
LVCOLUMN col;
e poi ai SetColumn() passi &col (il puntatore).
(Forse il fatto di aver visto che SetColumn() vuole come parametro un 
puntatore ti ha indotto ad allocare l'istanza di LVCOLUMN con new? ...)
Poi, errore di MFC: hai letto la documentazione di LVCOLUMN?? Lo sai che 
devi impostare un campo "mask" per indicare quale dei campi di LVCOLUMN 
vuoi settare?
Hai provato con:
col.mask = LVCF_WIDTH;
?
Insomma, C++ ed MFC non sono Visual Basic 6, in cui un approccio 
"drag-and-drop, riprova e correggi" funziona granche', senza delle 
solide basi teoriche, e molta attenzione al codice che si scrive.
<<Prima di imparare a correre, imparare a camminare>>
(saggio detto cinese)
Ciao, e buono studio

 Non lo deallochi mai, mi pare! Giusto?
Pensavo una cosa: se ti interessa lavorare con un linguaggio C-like, ma 
meno complesso del C++, e non hai molto tempo da dedicare allo studio di 
C++ ed MFC, hai pensato a C# + .NET?
Usando questa piattaforma, non avrai problemi di complessita' tipici del 
C++ o di MFC, e potrai "buttarti" sullo sviluppo del codice, senza 
pensare, ad esempio, che se invochi "new" da qualche parte, da qualche 
altra parte dovra' esserci una "delete"...
Ciao

Ciao, e buono studio
Grazie, ma tengo duro maledizione.. !
:))



In effetti avevo pensato allo C# !
Solo che avendo cominciato questo poi...non ho approfondito anche perchè l'ho scoperto dopo che ho cominciato che c'era il C#.
Cmnq ci sono anche delle altre motivazioni per le quali ho cominciato in C e per le quali vorrei provare a continuare.

 wrote:
Mi pare di esserci riuscito...!
se alla fine della funzione 
void CTabelleDati::OnHdnEndtrackListaTabella(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
	LVCOLUMN Col;
	Col.cx=50;//lCol[phdr->iItem];
	Col.mask = LVCF_WIDTH;
	m_Lista_Tabella.SetColumn(phdr->iItem,&Col);
	*pResult = 1;
}
*pResult lo passo a 1 invece che a 0, funziona!!
Andrà bene?
Grazie
Ciao
F


E, quando il controllo e' locked (ovvero non si vuole che l'utente possa 
modificare le dimensioni orizzontali del divisore dell'header-control), 
si ritorna proprio TRUE (1).:
<CODE>
//////////////////
// The header will send either HDN_BEGINTRACKA or HDN_BEGINTRACKW
// depending on how your parent list control responds to
// WM_NOTIFYFORMAT (default=HDN_BEGINTRACKW, Unicode). But if you're
// implementing a control to be used in any app, you should handle both
// notifications if you want it to work in either situation.
//
// Since OnChildNotify is virtual, all you have to do is override
// it—no need for message map entries to handle HDN_BEGINTRACKA/W.
//
BOOL CLockableHeader::OnChildNotify(UINT msg, WPARAM wp, LPARAM lp,
    LRESULT* pRes)
{
    NMHDR& nmh = *(NMHDR*)lp;
    if (nmh.code == HDN_BEGINTRACKA || nmh.code == HDN_BEGINTRACKW) {
       if (m_bLocked)
          return *pRes=TRUE; // eat message to disallow sizing
    }
    // otherwise, pass to header control for default processing
    return CHeaderCtrl::OnChildNotify(msg, wp, lp, pRes);
}
</CODE>

 In effetti, per quanto strano, bisogna "abilitare" il campo che si decide di usare.
Questa e' una filosofia molto diffusa nella programmazione Win32 (ed 
MFC; quella struttura LVCOLUMN e' ereditata dal mondo Win32, come spesso 
accade con MFC).
Quando hai una struttura con molti campi, non tutti obbligatori, devi 
indicare al sistema quali campi sono significativi.
...Non so se lo stesso accade anche con C# e .NET (sarei curioso a 
riguardo...).
Ciao

HDN_BEGINTRACK etc.)
Grazie.