From this article Unit testing with mock objects in C:
This is done by using the --wrap linker option which takes the name of the wrapped function as an argument. If the test was compiled using gcc, the invocation might look like:
$ gcc -g -Wl,--wrap=chef_cook waiter_test.c chef.c
How can I do this when compiling a C project in visual studio?
The --wrap in ld can be emulated by the /ALTERNATENAME option in MSVC Linker.
We start from two compilation units, say foo.o compiled from foo.c, whose external functions are declared in foo.h, and main.o from main.c.
(If foo has been compiled as a library, things won't change much.)
// foo.h
int foo();
// foo.c
int foo() {
return 0;
}
// main.c
#include <stdio.h>
#include "foo.h"
int main() {
int x = foo();
printf("%s\n", x ? "wrapped" : "original");
}
The return value of int foo() is 0, so the snippet of code above will output "original".
Now we override the actual implementation by an alias: The #include "foo.h" in main.c is replaced by
#define foo real_foo
#include "foo.h"
#undef foo
#pragma comment(linker, "/alternatename:real_foo=foo")
Let me explain what happens here:
by #define foo real_foo, the function declaration in foo.h is modified as int real_foo().
However, the symbol in foo.o is still named after int foo(), instead of the alias int real_foo(). That's why we need the /alternatename linker switch.
"/alternatename:real_foo=foo" tells the linker that, if you cannot find the symbol called real_foo, try foo again before throwing an error.
Apparently there is no definition of int real_foo(). MSVC Linker will search for int foo() and link it instead at each occurrence of int real_foo().
As the previous implementation has been aliased, now we redirect int foo() to our new implementation by a macro:
int wrap_foo() {
return real_foo() + 1;
}
#define foo wrap_foo
And we are done here. At last the main.cpp looks like:
#include <stdio.h>
#define foo real_foo
#include "foo.h"
#undef foo
#pragma comment(linker, "/alternatename:real_foo=foo")
int wrap_foo() {
return real_foo() + 1;
}
#define foo wrap_foo
int main() {
int x = foo();
printf("%s\n", x ? "wrapped" : "original");
}
Built in MSVC, it will output "wrapped".
Related
Like the title says, I want to create a system where two programs can access and modify the same global variable.
I've created a directory that has the files 1.c, 2.c, foo.c, and foo.h.
1.c:
#include <unistd.h>
#include <stdio.h>
#include "foo.h"
int main(){
printf("foo is %d\n", foo);
sleep(7);
printf("now foo is %d\n", foo);
}
2.c:
#include <stdio.h>
#include "foo.h"
int main(){
increment();
printf("2.c is incrementing foo. foo is now %d\n", foo);
}
foo.h:
#ifndef FOO_H
#define FOO_H
extern int foo;
void increment(void);
#endif
foo.c:
#include <stdlib.h>
#include "foo.h"
int foo = 5;
void increment(){
++foo;
}
I compile with the following compilation commands:
gcc -c foo.c
gcc 1.c foo.o -o 1.out
gcc 2.c foo.o -o 2.out
And then I run it with ./1.out ./2.out, ensuring that 2.out runs before the sleep() finishes in 1.out. The result is the following:
./1.out
foo is 5
now foo is 5
./2.out
2.c is incrementing foo. foo is now 6
My theory is that when 1.c and 2.c are linked with foo.o, they both get their own local copies of foo, and thus when one program modifies foo the other program's version goes unmodified. Is it possible to create one global variable that can be shared and modified across multiple files?
In C, global variables are global to the execution unit (process), not global to the execution environment (system). Standard C does not provide a mechanism to share memory between processes. However, your platform (Linux, Windows, MacOS, etc.) probably does. Look up "shared memory".
I am trying to create a struct in a header file, and initialize a template struct. For some reason, when including the header file in multiple files, it gives me the following error:
gcc foo.c bar.c -o foo -Wall
duplicate symbol _MYFOO in:
/var/folders/s4/zyw5lgk92wj9ljnsypgwdccr0000gn/T/foo-52f8fc.o
/var/folders/s4/zyw5lgk92wj9ljnsypgwdccr0000gn/T/bar-6dc21f.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
These are my files:
Bar.c:
#include "bar.h"
#include <stdio.h>
void helloWorld() {
printf("Hello world\n");
}
Bar.h
typedef struct Foo Foo;
struct Foo {
int number;
} MYFOO = {2};
void helloWorld(void);
Foo.c
#include "bar.h"
int main() {
helloWorld();
}
Interestingly enough, when I remove the line containing
MYFOO = {2};
The code compiles and works perfectly fine. I believe it has to do with including Bar.h twice, which ends up including that struct twice? But how would I avoid something like that?
Thank you!
You could add a directive to the Bar.h file to check if the file has already been included:
#ifndef _BAR_H_INCLUDED_
// Bar.h not included - declare your structs, etc, here.
// Define _BAR_H_INCLUDED_ to indicate this file has already
// been included
#define _BAR_H_INCLUDED_ 1
#endif
This should at least prevent you including Bar.h multiple times.
EDIT
A better solution might be to include the Bar.c from within the Bar.h:
// Bar.h
#ifndef _BAR_C_INCLUDED_
// code here
// Include Bar.c
#include "Bar.c"
#define _BAR_C_INCLUDED_
#endif
You can then simply include Bar.h in your Foo.c:
// Foo.c
#include <stdio.h>
#include <stdlib.h>
#include "Bar.h"
int main() {
//...
Then to compile:
gcc Foo.c -o Foo
So - here is your updated code - first, Bar.h
#ifndef _BAR_C_INCLUDED_
typedef struct Foo Foo;
struct Foo {
int number;
} MYFOO = {2};
void helloWorld (void);
#include "Bar.c"
#define _BAR_C_INCLUDED_
#endif
Now Bar.c:
void helloWorld() {
printf("Hello world\n");
}
Lastly, Foo.c - include stdio.h here as well as Bar.h (which will, in turn, include Bar.c for us):
#include <stdio.h>
#include "bar.h"
int main() {
helloWorld();
}
And to compile:
gcc Foo.c -o Foo -Wall
After toying around some more, I found the reason for the error coming from the line MYFOO = {2};
It had to do with the fact that I was initializing the struct in my header file.
Header files are meant for definitions, not initializations.
Instead, the solution for the problem was to simply define and initialize the line in the corresponding source file Foo.c.
Now, in that file I included as a global variable:
Foo MYFOO = {2};
Now to access this variable in any other file, such as in my Bar.c, all I needed to do was include the line,
extern Foo MYFOO;
This solved my problem for compilation and meant that I could use the struct in other files as desired!
consider the following code, which causes a weird behavior:
foo.h
#ifndef FOO_H
#define FOO_H
void foo();
#endif
foo.c
#include <stdio.h>
// NOTICE - foo.h is not included!
void foo()
{
printf("foo!\n");
}
main.c
#include "foo.h"
int main()
{
foo();
return 0;
}
running this code I get in the console: foo!
what bugs me here is that I expected that main.c would not be familiar with the implementation of foo(), since foo.h is not included in foo.c, and hence foo() should be an inner function in foo.c. It happened to me both when I ran it in VS2010 and when I compiled an exe using gcc (on windows).
can someone explain this phenomenon? I thought about it and I have no idea why it happens. thanks.
The header file is declaring the function, so when compiling main.c the compiler knows the function signature to validate against. When compiling foo.c, it doesn't need to be declared, as it is the declaration of the function. It is up to the linker to see if there are any unresolved symbols, which there aren't in this case, so all is good, and also why you're seeing this work.
What will happen if there was another function(test.c) included in the above question.
foo.h
#ifndef FOO_H
#define FOO_H
void foo();
#endif
foo.c
#include <stdio.h>
// NOTICE - foo.h is not included!
void foo()
{
printf("foo!\n");
}
test.c
#include <stdio.h>
void foo()
{
printf("foo!\n");
}
main.c
#include "foo.h"
int main()
{
foo();
return 0;
}
I had created this minimal example to illustrate my problem with extern declaration with Visual Studio 2008 (required to compile a python 2.7 extension). The same example is working well with gcc.
The result is that I have 2 separate global_var variables instead of a unique one in lib.c
the library interface : lib.h
#ifndef LIB_H
#define LIB_H 1
int __declspec( dllexport ) displayGlob();
#endif // LIB_H
the library code
// lib.c
#include<stdio.h>
int global_var=2;
int __declspec( dllexport ) displayGlob() {
printf("lib.c global_var=%d\n", global_var);
return global_var;
}
the user code that uses the library variable "global_var" and function displayGlob()
// main.c
#include"lib.h"
#include<stdio.h>
#include<stdlib.h>
extern int global_var=0; // must be initialized otherwise "error LNK2001: unresolved external symbol global_var"
int main(int argc, char *argv[])
{
printf("main.c global_var=%d\n", global_var);
displayGlob();
global_var = 3;
printf("main.c global_var=%d\n", global_var);
displayGlob();
exit(0);
}
execution result is:
main.c global_var=0
lib.c global_var=2
main.c global_var=3
lib.c global_var=2
Questions:
1 - Why must I initialize the extern variable in lib.h with Visual Studio and not Gcc ?
2 - Why the global_var lib.c displayed by the second displayGlob() is not modified to 3 ?
thanks for any hint !
Laurent
UPDATE: moved extern declaration of global_var from lib.h to main.c (even simpler example)
and of course problems remain...
Because C preprocesor basically pastes the content when you call #include, it the same as you declared your extern inside of main.c file. This means that this symbol is defined twice (in main.c and in lib.c).
What you should do is to add extern declaration to lib.c (for example by including lib.h) and initialize the value there, then remove initialization from lib.h.
So it should be like this:
lib.h:
extern global_var;
lib.c:
#include "lib.h"
int global_var=2;
main.c
#include "lib.h"
(no global_var definition/declaration here)
Solved myself, my fault.
Under Gcc I built both a static library and a dynamic library. My main.c was linked with the STATIC library, so variable resolution between lib.c and main.c was resolved at link time. I forgot that.
Under Visual Studio, I only built a DYNAMIC library, so it was normal variable linkage could not happen between the DLL and main.o
Sorry for any confusion created...
I am currently working on my first "serious" C project, a 16-bit vm. When I split up the files form one big source file into multiple source files, the linker (whether invoked through clang, gcc, cc, or ld) spits out a the error:
ld: duplicate symbol _registers in register.o and main.o for inferred
architecture x86_64
There is no declaration of registers anywhere in the main file. It is a uint16_t array if that helps. I am on Mac OS 10.7.3 using the built in compilers (not GNU gcc). Any help?
It sounds like you've defined a variable in a header then included that in two different source files.
First you have to understand the distinction between declaring something (declaring that it exists somewhere) and defining it (actually creating it). Let's say you have the following files:
header.h:
void printIt(void); // a declaration.
int xyzzy; // a definition.
main.c:
#include "header.h"
int main (void) {
xyzzy = 42;
printIt();
return 0;
}
other.c:
#include <stdio.h>
#include "header.h"
void printIt (void) { // a definition.
printf ("%d\n", xyzzy);
}
When you compile the C programs, each of the resultant object files will get a variable called xyzzy since you effectively defined it in both by including the header. That means when the linker tries to combine the two objects, it runs into a problem with multiple definitions.
The solution is to declare things in header files and define them in C files, such as with:
header.h:
void printIt(void); // a declaration.
extern int xyzzy; // a declaration.
main.c:
#include "header.h"
int xyzzy; // a definition.
int main (void) {
xyzzy = 42;
printIt();
return 0;
}
other.c:
#include <stdio.h>
#include "header.h"
void printIt (void) { // a definition.
printf ("%d\n", xyzzy);
}
That way, other.c knows that xyzzy exists, but only main.c creates it.