How to avoid "multiple definition" error for global constants? - c

I'm writing a C program using the Windows API. Each major function has its own file, and there is one header for the prototypes and includes and whatnot:
// Headers & global constants
#pragma once
#define _WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <WindowsX.h>
#include <Windef.h>
#define szClassName TEXT("EthicsPresentationWnd")
// Prototypes
LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK FontProc1(HWND hWnd, LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
ATOM RegisterWindow(HINSTANCE hInstance);
The thing I'm irritated about is the #define szClassName line. I dislike using macros and would prefer to have a proper global variable, wchar_t szClassName[], but if I do that then the linker complains about multiply defined variables in each of the modules that include the header.
I thought the #pragma once directive would prevent this, but it didn't.
Is there any solution to this problem?

The solution to this is to have a separate declaration and definition...
Header (*.h; sorry, I don't know WinAPI type names, adapt as necessary):
extern const char szClassName[];
Implementation (*.c or *.cpp)
const char szClassName[] = "hello, world"
You're seeing the problem because a new symbol szClassName is being declared each time one of your *.c or *.cpp files includes the header (even with the include guards!); and that makes the linker confused (see below).
Do note that this will make sizeof(szClassName) not work anymore.
Further explanation:
After preprocessing, the compiler is basically seeing this:
file "a.c": const char someSymbol[] = <some text, don't care what right now>;
file "b.c": const char someSymbol[] = <some text, don't care if it's the same>;
file "c.c": const char someSymbol[] = <some text, ditto>;
When the linker is linking the object files (say, "a.obj", "b.obj" and "c.obj"), it sees the same symbol being defined with a new value (at least as far as the linker is concerned) --- and thus it fails with an error.

Place it in between
#ifndef GLOB_CONST_H
#define GLOB_CONST_H
// All macro definitions
// and type definitions
#endif
Use extern keyword to declare your global variables and put those declarations in this header file. After that you need to place the definition of all the variables in a .c file.

You can declare the variable as static so that each module that includes the .h file gets its own local unique copy that the linker will not complain about, as each copy will have local linkage instead of external linkage. This also eliminates the need for declaring the variable as extern and defining it in a separate .c file.
static const TCHAR szClassName[] = TEXT("EthicsPresentationWnd");
Or;
static const TCHAR *szClassName = TEXT("EthicsPresentationWnd");
Or:
static LPCTSTR szClassName = TEXT("EthicsPresentationWnd");

Use header guards in all your header file and declare a global variable in .c file and declare extern to that global variable in a header file.
#ifndef HEADER_FILE_NAME_H /* if not defined already */
#define HEADER_FILE_NAME_H
extern wchar_t szClassName[];
#endif
In any one of your .c file define the global variable.
wchar_t szClassName[];

Related

Errors due to static inline version of a earlier non-static non-inline function

I have a function which is initially declared in a header file my.h to have external linkage(no storage class specified)
int myfunc(int);
And this function definition and it's call is present in source file my.c
my.c includes my.h
This all is fine.
But now I wanted to make this function myfunc inline
So I declare a new prototype in my.c
as
__attribute__((always_inline)) static inline int myfunc(int)
and define it so in same function as before,
as expected I keep getting an error saying
static declaration of 'myfunc' follows non-static declaration
I need to keep the non-static,non-inline version of this function for a C reference version of code , and the static inline version for a optimized version of the code.
How can I work around this problem , as I need a static declaration of that function., within this existing source/header files setup I have
One way is I change the name of the static inline function to myfuncinline and work with it!
But is there any way within current setup.
A function defined with static storage-class specifier has internal linkage. You cannot refer to it outside that translation unit.
If you cannot change the declaration of myfunc in the header, then write two
functions in the source file. One called myfuncreal, which does all the work and is defined with static inline:
__attribute__((always_inline)) static inline int myfuncreal(int a)
{
//uses parameter a and returns the result
}
And the other called myreal that wraps around myfuncreal, defined as:
int myfunc(int a)
{
return myfuncreal(a);
}
#ifndef DEBUG
static inline
#endif
int myfunc(int);
Assuming DEBUG is defined in your debug builds but not in your optimized builds. Note that this example is for a declaration in a .c file or a definition in a .h file; for a declaration in a .h and a definition in a .c do
/* foo.h */
#ifdef DEBUG
int myfunc(int);
#endif
/* foo.c */
#ifndef DEBUG
static inline int myfunc(int);
#endif
/* code that uses myfunc() */
#ifndef DEBUG
static inline
#endif
int myfunc(int) {/* definition */}

C - extern, static, include

Scoping in C is confusing as hell. I have a variable: "int qwe". This var should be visible in one or more files - f1.c in this case, but not the another f2.c .
Say i have: main.c, f1.c, f2.c, header.h
main:
call f1();
call f2();
header:
#ifndef HEADER_INCLUDED
#define HEADER_INCLUDED
int qwe = 1;
void f1();
void f2();
#endif // HEADER_INCLUDED
f1.c:
#include <stdio.h>
extern int qwe;
void f1(){
printf("In f1: %d\n", qwe);
}
f2.c:
#include <stdio.h>
static int qwe = 2;
void f2(){
printf("In f2: %d\n", qwe);
}
Now this gets confusing. There is definition and declaration. I have defined qwe in the header, declared it in f1.c. Is that correct? Should definition happen in header and declaration in f1.c instead? I tried the latter case, but got an error - "multiple definition of qwe". When i removed the #include directive from f1.c, it worked... It also works when i remove the extern keyword. Is extern redundant?
f2.c i guess it's ok and behaves as expected, or is it? But if i put an #include with header, it breaks. Why is that?
When should i use #include in source files? If i don't include it f1.c or f2.c it works...
Also, if i define a variable as static inside a function, like static int i = 0; This variable will not be destroyed when function exist, it will keep it's memory and data. And next time that same function gets called, will have access to it, right? But the var won't be reinitialized to 0, i.e. the line where is defines won't execute. Correct?
Life stomps me :(
In the header, declare the variable. In e.g f1.c, define the variable, e.g. int qwe = 1; // at global scope.
In all files that want to see/change qwe, include the header that declares the variable. Easy-peasy.
You need to declare the variable in the header, and define it in one and only one C file.
In C, you cannot have a variable that doesn't "belong" to a given translation unit (source file). So it must be defined by exactly one translation unit in the whole program.
When you declare a variable as extern, you're telling the compiler the symbol is (possibly) external to your translation unit (c file).
It's probably also worth noting that when you try to declare a variable without extern, the variable is also defined, e.g.:
/* Declares, but does not defines external symbol 'foo' */
extern int foo;
/* Both declares AND defines bar */
int bar;
This is also different from how functions work to where the "default" syntax for declaration does NOT define a function:
/* Declare, but don't define spam */
void spam(void);
/* Declare, but don't define eggs */
extern void eggs(void);
/* Declare & define 'cheese' */
void cheese(void){ return; }
So your example should look more like this:
qwe.h:
#ifndef QWE_H
#define QWE_H
/* Declare qwe here */
extern int qwe;
#endif
f1.c:
/* DEFINE qwe here */
int qwe = 1;
f2.c:
#include "qwe.h" /*header includes the `extern int qwe` declaration */
void my_function(void)
{
/* use external symbol here! */
qwe = 10;
}
The scoping system isn't that confusing. The rule is this:
if you define something in a .c file EVERY other .c file in your program can access it (it is put in the global namespace).
if you specify static in front of its definition then only things in the SAME file can see it. This should be your default position for all functions and variables you don't want other .c files to be able to access.
It is very important to remember that extern only tells the compiler that the variable/function in question is not defined in the current file. This prevents the compiler for otherwise issuing an error because it can't find the symbol, but it has nothing to do with scoping - your .c file sees everything in the global namespace and if you have not followed the second part of the rule you will quickly find out about this at link time.
Header files similarly have nothing to do with scoping. They are just convenient places to put a bunch of extern statements and macros.
In C, you should use the header file in general to declare the data but not define the data. You don't want to define global data in a header because it will then be redundantly defined in multiple modules. The header indicates to multiple modules the existence of some data or function somewhere and what its type is, as well as common constants and macros (#defines). Outside of that, things in C are very simple. Just about anything is, technically, global unless you declare it static, keeping it scoped to the module it's defined in. The extern declarations for data in the headers and the function prototypes help the compiler know that these items are being accessed by a particular module and what the data types are for access so that the correct code can be generated.
You have:
Two functions f1 and f2 that are defined in separate modules but used in main. So these need to be declared in a header file.
A global data item qwe being used in more than one module.
A static qwe used in one module.
Assuming you want this done with one header file (you might need separate ones for f1, f2, and global data - see below), you could set up
your header as:
#ifndef MY_HEADER_H
#define MY_HEADER_H
extern int qwe;
void f1(void);
void f2(void);
#endif // MY_HEADER_H
Then in your main.c:
...
#include "my_header.h"
int qwe; // This is global and can be accessed from other modules
void main(...)
{
// call f1
// call f2
...
I just defined the global variable, qwe, in main.c arbitrarily. If you have a few globals, you can define them in their own glob_data.c module, for example, and have it's own header, glob_data.h, to declare them. Any other module that needs to access them would include the glob_data.h header so that compilation can properly be done on that module to access that data. Keeping the global data in separate headers helps with cases like you have where you have a static instance of the data versus the global, which are in conflict. You can avoid including the data header file for that global item when you want to compile with the static item.
Then in your C file, f1.c:
...system headers included...
#include "my_header.h"
void f1() {
printf("In f1: %d\n", qwe);
}
And in f2.c:
...system headers included...
#include "my_header.h" // Only if it doesn't contain `extern int qwe;`
static int qwe = 2; // This hides the global qwe and is known only
// to f2.c
void f2(){
printf("In f2: %d\n", qwe);
}
As I mentioned above, you might want to separate your function prototypes and your global data declaration in separate headers. That way, you can include only what's needed in each module and avoid conflicts, such as when you have a static int qwe; versus the global int qwe;.
I have defined qwe in the header, declared it in f1.c. Is that correct?
No, it should be the other way around. You are supposed to have a definition of a global variable in a single translation unit (that's geek speak for a .C file) but you may declare it in as many translation units as you wish. Since headers potentially get included from many translation units, declarations go in the headers.
When should i use #include in source files?
You do it when the header has anything that is needed for your translation unit to compile, with very few exceptions. Note that in some situations it may be necessary or desirable to make a forward declaration manually without including the header.
Also, if I define a variable as static inside a function, like static int i = 0; This variable will not be destroyed when function exist, it will keep it's memory and data.
That is correct, the static variable inside the function will be assigned the initial value only once, and retain the value that you assign to it for as long as your program continues to run.

C - properly importing stdcall functions from unmanaged DLL

I am trying to import a function from an unmanaged DLL into a C project by creating a .def file specifying the function I need to use. I am practicing on the WinAPI function MessageBoxA from user32.dll. It is an stdcall function, like the other WinAPI functions.
Here's how I create my .def file:
LIBRARY user32.dll
EXPORTS
_MessageBoxA#16
Then I create a .lib from it like this: lib /def:"C:\Path\to\def\user32.def" /
out:"C:\path\to\project\user32-mb.lib" which successfully creates user32-mb.lib and user32-mb.exp. Then, in my C project, I do the following:
#pragma comment(lib, "user32-mb.lib")
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
EXTERNC __declspec(dllexport) int __stdcall MessageBoxA(void *hWnd, char *lpText, char *lpCaption, int uType);
void main(){
MessageBoxA(0, "MessageBox test", "MessageBox test", 0x00000030L);
}
However, upon linking, it gives the following error:
error LNK2019: unresolved external symbol _MessageBoxA#16 referenced in function _main
However, when I change the declaration in the .def to this:
LIBRARY user32.dll
EXPORTS
MessageBoxA
And change the function prototype in my C code to cdecl instead of stdcall:
EXTERNC __declspec(dllexport) int __cdecl MessageBoxA(void *hWnd, char *lpText, char *lpCaption, int uType);
The message box actually appears, but right on closing, it throws an error:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
Which indicates that calling it with cdecl is also a bad idea since it requires stdcall after all.
The question is, what should I change in the .def file or in my project to avoid both errors and to import and call an stdcall function properly?
You need to change __declspec(dllexport) to __declspec(dllimport), as you are importing functions from a DLL, not exporting them:
EXTERNC __declspec(dllimport) int __stdcall MessageBoxA(void *hWnd, char *lpText, char *lpCaption, int uType);
^^
You need to use dllimport rather than dllexport, but in this case you should remove the __declspec(...) altogether.
And you need to specify the correct name for the function which is MessageBoxA.
LIBRARY USER32.dll
EXPORTS
MessageBoxA
Also it would be remiss of me not to point out that the correct main declaration is
int main(void)
I am still not entirely sure why, but removing the _ adding the ordinal to the function name my .def file fixed everything. My solution is:
LIBRARY USER32.dll
EXPORTS
MessageBoxA#16 #2093
Function definition:
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void *PVOID;
typedef PVOID HANDLE;
typedef HANDLE HWND;
typedef const char *LPCSTR;
typedef unsigned int UINT;
EXTERNC __declspec(dllimport)
int
__stdcall
MessageBoxA(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType);
This page indicates that winuser.h is the header. From there, you can see some macros are used, including WINUSERAPI and WINAPI. WINUSERAPI is conditionally #define-d at the beginning of that header. WINAPI can be found in the winbase.h header, where it can be seen to be tied to a calling convention, depending on the platform.
But a better question is: Why are you using dllexport and not dllimport?

#ifdef in c for filename for guarding static function in header file

I have a situation in which i have a header file and that has to be included in more than one file. It has some static function prototypes. I want to do something like this
#ifdef filename.c
static foo(void );
static bar(int );
#endif
Which means if I include this in a file with name filename.c it those function prototypes are active and if included in some other file they are quiet.
filename.c is a relative uncommon symbol. Apart from that, you would need to explicitly define a symbol in your filename.c-file. Like:
#ifdef FILENAME_C_
static foo(void );
static bar(int );
#endif
And in your filename.c-file
#define FILENAME_C_
You should prefer the underscore _-version in FILENAME_C_, it is more common and easier to read.
Yet, I don't understand why you would declare those functions only? You would need to define them anyway in your filename.c-file. What do you want to achieve with this?

problem in dll call in writing the calling process

I have following function defined in one dll:
__declspec( dllexport ) int __stdcall
mjscall(char *cmd, DWORD wtime, char *stdoutfile, char *stderrfile )
I need to write one process to call the above function.
I am doing it first time,I do not have much idea.
I have written the following code
#include <windows.h>
#include <windows.h>
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <limits.h>
extern __declspec( dllexport ) int __stdcall mjscall(char *cmd, DWORD wtime, char *stdoutfile, char *stderrfile );
typedef INT (*MJSCALL) (char *,DWORD, char *, char *);
int main()
{
char *a,*b,*c;
a=NULL;
b=NULL;
c=NULL;
DWORD aa =1;
int i;
HMODULE hLib;
MJSCALL ADD;
hLib=LoadLibrary("f3cucall.dll");
if(hLib==NULL)
{
return 1;
}
ADD=(MJSCALL)GetProcAddress(hLib,"mjscall");
if (ADD==NULL)
{
return 1;
}
(ADD)(a,aa,b,c);
return 0;
}
The "(ADD)(a,aa,b,c);" is causing the problem.
Can somebody help me out?
I think you mixed two things up:
the __declspec(dllexport) MSVC keyword exports functions from a DLL (tells the linker to do so), and the __declspec(dllimport) imports functions from a DLL. This is done at loading time, the linker will create all the necessary code to load the DLL and resolve the symbol. In fact, it adds some code to the exe to let the OS load the DLL. You can use functions declared with __declspec(dllimport) just like any normal internal function.
If you want to use this approach, you need the DLL's lib file, since it contains information for the linker to resolve the symbolic name. It doesn't actually contain code, only these information on the DLL for the linker. Additionally, you have to tell the linker that the function you want to use is located at a DLL, using the magic __declspec(dllimport) before the function declaration. That's why you provide a .lib and a header file (containing these declarations) with your DLL if you want to do it this way. You should rebuild the project that uses the DLL when you change the DLL, as the .lib file may have changed.
You can use the same header file in your DLL project and the projects that import from this DLL:
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
MYDLL_API void printMe(int);
The MyDLL_API get resolved to either __declspec(dllexport) (in the DLL project, where you define the MYDLL_EXPORTS in the project settings) or __declspec(dllimport) (in all projects that use the dll). This way, you only need one header file for the DLL.
Another method of calling DLL functions is to use LoadLibrary and GetProcAdress. These two are used to load a DLL at runtime. The main difference between loading a DLL at loading time and at runtime is that you have some control over loading the DLL at runtime, whereas the OS will do the job when the DLL is to load at loading time (e.g. show a message box if the DLL cannot be found and do not run the process).

Resources