Alright so I am writing this spell checker program in Visual C++. Until now, all the code was written in a single CPP file. What I want to do now is to separate the source code files and link them together. I know that with VC++, you don't have to create the whole make file again (although you could do that manually). However, when I separate the code into a CPP file and create its H file, I get like 102 errors. The error files are like these:

D:\Download.com\Adrian\Adrian.cpp(67) : error C2065: 'Font1' : undeclared identifier
D:\Download.com\Adrian\Adrian.cpp(68) : error C2440: '=' : cannot convert from 'struct HFONT__ *' to 'int'
        This conversion requires a reinterpret_cast, a C-style cast or function-style cast
D:\Download.com\Adrian\Adrian.cpp(77) : error C2065: 'IDI_ADRIAN' : undeclared identifier
D:\Download.com\Adrian\Adrian.cpp(80) : error C2065: 'IDC_ADRIAN' : undeclared identifier
D:\Download.com\Adrian\Adrian.cpp(81) : error C2065: 'szWindowClass' : undeclared identifier
D:\Download.com\Adrian\Adrian.cpp(81) : error C2440: '=' : cannot convert from 'int' to 'const char *'
        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast


The problem is, I believe, that my second source file is using some of the resources that are in the first file and vice versa. So they are somehow interlinked. I have tried everything but it's just giving me a headache. Can anybody please tell me how you separate your source code in VC++ into different source files?

I looked in MSDN and also searched in Google but I didn't find anything that was really helping me with this.
Posted on 2007-12-26 08:25:49 by XCHG
Heh, if you've never programmed "properly" before, this is going to take a whole lot of explaining :P

Split your code into logical "modules". For instance, one set of {.h, .cpp} files for each dialog/window, a set of {.h, .cpp} files for utility routines, etc. The .h file contains function prototypes and type definitions, constants, etc. that's necessary to use the "module". The .cpp file includes it's corresponding .h file, along with any other .h files it will need. Try not to create too many interdependencies, as that can lead to recompile hell (make one minor change, and *boom* all your source files need to recompile).

main.cpp should be as small as possible, with it's "int main(int argc, char* argv[])" (or WinMain) and function as a "driver module" (NOT related to operating system drivers :)) that "drives" the components in your other modules.

You'll need to include "resource.h" for just about everything that uses resources, and for the kind of code you do, you'll probably need windows.h as well. Headers that change very infrequently, or not at all, (windows.h + friends from the PlatformSDK and other system headers) can be put in a "precompiled.h" and you can then take advantage of precompiled headers to speed up compilation.
Posted on 2007-12-26 09:58:17 by f0dder

Heh, if you've never programmed "properly" before, this is going to take a whole lot of explaining :P


Oh believe me; I have programmed "properly" before  :lol:

Thank you for your reply f0dder but that was not my question  :sad: I know what is wrong but I don't know how to fix it. It is a simple problem. I have already tried creating .h files and .cpp files and it simply works. However, for this project, I have to use have various cpp and h files each of which could be interlinked to the other functions/procedures on other source files. There are globally shared variables also. I am using VC++ because I know it automatically generates the make file.
Posted on 2007-12-26 17:06:16 by XCHG
So, your problem is just in sharing same global variable in two objects?

Or something else?
Posted on 2007-12-26 18:56:12 by vid
Sorry, but it doesn't sound like you've been programming "properly" if a thing like this causes you problems :)

It isn't that hard, really - for each of your .cpp files, you need to create a .h file with function prototypes and extern declarations. For each of your .cpp files, you need to know/find your dependencies, and include the proper .h file. No simpler than that, no more complex either.

Globally shared variables?


#include "global.h"
int my_shared_variable;
static int my_private_variable;
bool my_shared_func(int arg) { return arg != 0; }
static int my_private_func() { return 42; }


#ifdef __cplusplus
extern "C" {
#endif

extern int my_shared_variable;
extern bool my_shared_func(int arg);

#ifdef __cplusplus
}
#endif



#include "global.h"

int main(int argc, char* argv[])
{
  my_shared_variable = 42;
  my_shared_func(my_shared_variable);
  return 0;
}
Posted on 2007-12-26 19:53:19 by f0dder
f0dder: wrong :P
Declaration of shared global variables in C is really fscked up.

Following code creates DEPENDENCY on external "x", it doesn't define it:

extern int x;
int x;


To declare shared variable, simply put following into header file:

int my_shared_variable;

You can have following in multiple object files, and linker will merge it into single variable. Tested with MSVC and MinGW GCC. I wasn't able to replicate this type of exporting symbol in any assembler except MASM.

MASM uses this:

COMM my_shared_variable:DWORD


COMM is like EXTERN, but in case linker finds only COMMs of symbol and no PUBLIC, it creates the variable.

If you initialize variable, it will be normal public symbol (and all other COMM will become reference to this one).

Posted on 2007-12-27 04:39:29 by vid
Ugh, it's a bad piece of advice to depend on COMDEF.

Really, you declare the variable (with extern) in a header file, then you define it in a single translation unit (.c or .cpp). It work, and doesn't rely on linker magic (which will fail anyway if you define the symbols with different value).
Posted on 2007-12-27 06:28:53 by f0dder
I just discussed this with more experienced friend.

It looks like that MS's behavior with following code is incorrect:
extern int a;
int a;


Friend said that according to norm, there is no difference between these two. I tried with MinGW gcc, and it doesn't differentiate between "extern int a;" and "int a;".

Linker is supposed to collect all definitions of global variable, and leave just one in. Extern should be ignored. This isn't MS-specific hack, it is proper behavior.

So having "int a;" in header, and thus in multiple objects, is okay. When linking, it defines single variable. Using "extern" is dangerous because of MS's implementation, which is more logical (especially to us, ASM coders), but not according to specification.

Only difference is if you initialize the variable, in that case it is not COMM-like type, but it is PUBLIC / GLOBAL type. There can be only one such "real definition", and all COMMs will use that one. If there is no real definiton, linker uses one of COMM definitions. If there is more than one real definition, linker throws error. Even following code is proper real definition:
extern int a = 10;


In short, "extern" keyword shouldn't have any effect on global variable definition / declaration. However, in MSVC, it does have effect, so I would recommend not to use this keyword at all.
Posted on 2007-12-27 06:47:53 by vid
Go read The Standard. Bjarne uses "extern" for his header-file data declarations.

Imho defining variables in header files is a bit of a hack.

Inline functions and const declarations is a different story, though!
Posted on 2007-12-27 07:19:31 by f0dder
Shit, i just realized this topic was about C++, not C :)

My bad, all I told is about C, not C++. AFAIK, in C++ it works as expected, as f0dder told.
Posted on 2007-12-27 07:23:50 by vid
Humm, not sure about straight C, would have to check K&R's book... but I'm pretty sure it still applies there.
Posted on 2007-12-27 08:02:23 by f0dder
MinGW GCC does it as I say, and so does say friend's 1991 book about C. I quess this is one of insanities tha got fixed with C++
Posted on 2007-12-27 08:16:22 by vid
Well, C++ does handle "your" stupid way of doing definition in .h (and including multiple times) through the One Definition Rule, but I'm still pretty certain that plain C handles extern properly as well.
Posted on 2007-12-27 08:20:24 by f0dder
depends on what you define as "properly". I tell you that in "standard C" (eg. GCC implementation, something between C90 and C99), "extern" keyword has no effect on definition of global variables.

So if you have file that only has "extern int a;" in it, then this file defines "a", if it is not defined in any other file. If that is what you call "properly", then OK. Even "extern int a=5;" is proper definition.

Problem is that MSVC, even when compiling C file, applies C++ style of handling "extern". "extern" is not ignored on global variables, as it should be, but it has similar effect to C++ "extern". So MSVC-produced object file with "extern int a;" will never define "a", like one from GCC would. You have to define "a" in some other object file. That is why i would vote against using "extern" in C projects, because in proper C it has no effect, and in MSVC C it doesn't work.

But of course, this is offtopic, XCHG was asking about C++.
Posted on 2007-12-27 09:25:47 by vid
Well, any decent programmer would do extern in the .h and the definition in a .c file anyway, so even if MSVC doesn't follow the C standard here, then no worries. I'd still have to check up on K&R's book before saying anything more about C, though... GCC isn't necessarily always right :)
Posted on 2007-12-27 09:28:54 by f0dder
http://inst.eecs.berkeley.edu/~cs61c/resources/knr/chapter4.html#s4.4

Some notes:

*A plain "int a;" outside any function makes the variable "externable"

*Using extern in the very same source that defines the variable makes it forward-referencable (starting from the extern declaration to the definition).

*Using "static int a;" outside any function make the variable "private" to the source that defines is at the definition point (i.e. extern can reach it).

This book is old and perhaps this changed in C90 or C99, but it is pretty extrange the new behaviour :?
Posted on 2007-12-27 09:34:34 by LocoDelAssembly
From Loco's link:

On the other hand, if an external variable is to be referred to before it is defined, or if it is defined in a different source file from the one where it is being used, then an extern declaration is mandatory.


"Source file" should probably read "translation module" instead, to cover #include.
Posted on 2007-12-27 09:55:31 by f0dder
Loco: interesting, so that behavior isn't in K&R. Maybe this was a stupid addition of C89/C90 to K&R?
Posted on 2007-12-27 09:56:35 by vid
Oh, by the way:

f0dder@ayanami ~ $ cat > test.c
#include <stdio.h>

extern int a;
extern int b = 20;

int main()
{
        printf("%d, %d\n", a, b);
}
f0dder@ayanami ~ $ gcc test.c
test.c:4: warning: 'b' initialized and declared 'extern'
/tmp/ccwlWRMo.o: In function `main':
test.c:(.text+0xc): undefined reference to `a'
collect2: ld returned 1 exit status
f0dder@ayanami ~ $ gcc -version
gcc: unrecognized option '-version'
gcc: no input files
f0dder@ayanami ~ $ gcc --version
gcc (GCC) 4.1.1 (Gentoo 4.1.1-r3)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Morale: extern declaration (without definition part!) in .h file, single definition in .c or .cpp file.
Posted on 2007-12-27 10:13:23 by f0dder
f0dder: darn, looks like i screwed something in my previous experiment. GCC doesn't ignore "extern" like I said earlier.

You are right, "extern int a;" as declaration in header, and "int a;" as single definition works, both in C and C++, and both in GCC and MSVC.

Glad to have confusion finally resolved, i must have been high or something, because i 'd swear that same things didn't work as expected before, but they do work when i try now...  :/
Posted on 2007-12-27 11:00:16 by vid