i kept the essential.
caller.exe loads the dll, then calls the function dll_init declared inside the dll.
this last function calls the function "get_ptr" declared in the common library which should return a pointer to the global variable.
the issue is:
whenever caller.exe calls "get_ptr" it returns a valid pointer same as the one which was previously allocated on caller.exe start fine.
whenever the dll thru it function "dll_init" (after bein called by
caller.exe) calls "get_ptr" (knowing that the dll is linked to the
static lib) it return NULL pointer.
what i am missing ?
libcommon.c
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
/***************header****************/
int *get_ptr(void);
int set_ptr(void);
/**********************************/
int *global=NULL;
//extern __declspec(dllimport) int *global; doesnt work
int set_ptr() {
global = (int *) malloc(sizeof(int));
printf("global allocated to %p\n",global);
*global=485; //random value
return 0;
}
int *get_ptr() {
return global;
}
here is compiling commands (makefile simplified):
gcc.exe -c libcommon.c -o libcommon.o -m32
ar r libcommon.a libcommon.o
ranlib libcommon.a
module.c
#include <windows.h>
#include <stdio.h>
#if BUILDING_DLL
#define DLLIMPORT __declspec(dllexport)
#else
#define DLLIMPORT __declspec(dllimport)
#endif
DLLIMPORT int dll_init(void) {
int *ptr=(int *) get_ptr();
puts("dll run");
printf("from dll global: %p\n",ptr);
puts("dll end");
return 0;
}
compiling:
gcc.exe -c module.c -o module.o -m32 -DBUILDING_DLL=1
gcc.exe -shared module.o -o module.dll -static-libgcc -lws2_32 -m32 -s -L"." -lcommon -Wl,--output-def,libmodule.def,--out-implib,libmodule.a,--add-stdcall-alias
caller.c
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
typedef void(voidfunc)(void);
voidfunc *fct_ptr;
int test(int a) {
printf("%d",a++);
}
int main() {
set_ptr();
printf("::%p\n",get_ptr());
/* Load the dll then call dll_init */
HMODULE dllptr = LoadLibrary("module.dll");
if (dllptr != NULL) {
fct_ptr = (voidfunc *) GetProcAddress(dllptr, "dll_init");
puts("loaded");
if (fct_ptr != NULL)
fct_ptr();
FreeLibrary(dllptr);
}
}
compiling:
gcc.exe caller.c -o caller.exe -m32 -static-libgcc -lws2_32 -L. -lcommon -m32
I believe you have 2 different places in memory named global. One is
in caller since you compiled it statically with lcommon. Data is set
there via set_ptr. Second is in module space (for the same reasons),
but you never called set_ptr() there. Check memory address of global
inside dll_init and in main. If they are not the same, you then need
to call set_ptr in your `dll_init``
he's right, i think the common static library linked with both exe and dll was a wrong idea.
the solution is here: .dll Plugin that uses functions defined in the main executable
Any other suggestions are welcome
Related
I'm currently working on a C project, but I'm stuck on what seems to be a simple problem...
My files are main.c, main.h, fun1.c, fun2.c and fun3.c.
main.h is included in main.c, fun1, fun2 and fun3 (respectively in fun1.C, fun2.c and fun3.c files) are used by a function in main.c, and the fun1, fun2 and fun3 functions are declared in main.h like that:
extern int fun1(unsigned);
extern int fun2(int, int, int);
extern int fun3(int, int);
But when I try to compile the code, I get these errors
main.c:12: undefined reference to 'fun1'
main.c:17: undefined reference to 'fun2'
main.c:25: undefined reference to 'fun3'
Did I miss something about the way extern works? Thanks for your answers.
The project is actually a lot more complex since I am working on a kernel, but I simplified it. This is a work that my teacher gave me, and I'm trying to modify the code as less as possible, that's why I'm sticking to the use of extern.
UPDATE
As the problem seems to lie somewhere else, I'm going to show you my file system.
My files are sem.c, sem.h, semget.c, semctl.c and semop.c.
sem.h is included in sem.c, semget, semctl and semop (respectively in semget.C, semctl.c and semop.c files) are used by a function in sem.c, and the semget, semctl and semop functions are declared as extern in sem.h (same as before, just changed back the names).
At some point in the makefile (don't ask me what the makefile is doing, I have no idea because of its complexity), the file syscalls.c is used:
#include <nanvix/const.h>
#include <nanvix/syscall.h>
/*
* System calls table.
*/
PUBLIC void (*syscalls_table[NR_SYSCALLS])(void) = {
(void (*)(void))&sys_alarm,
...
(void (*)(void))&semget,
(void (*)(void))&semctl,
(void (*)(void))&semop
};
The syscalls.c file include the syscall.h file:
#ifndef NANVIX_SYSCALL_H_
#define NANVIX_SYSCALL_H_
#include <nanvix/const.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <ustat.h>
#include <utime.h>
/* Number of system calls. */
#define NR_SYSCALLS 51
/* System call numbers. */
#define NR_alarm 0
#define NR_brk 1
...
#define NR_semget 48
#define NR_semctl 49
#define NR_semop 50
#ifndef _ASM_FILE_
/* System calls prototypes. */
EXTERN unsigned sys_alarm(unsigned seconds);
EXTERN int sys_brk(void *ptr);
...
EXTERN int semget(unsigned key);
EXTERN int semctl(int semid, int cmd, int val);
EXTERN int semop(int semid, int op);
#endif /* _ASM_FILE_ */
#endif /* NANVIX_SYSCALL_H_ */
The exact error is what follows:
sys/syscalls.o:(.data+0xc0): undefined reference to `semget'
sys/syscalls.o:(.data+0xc4): undefined reference to `semctl'
sys/syscalls.o:(.data+0xc8): undefined reference to `semop'
sys/sem.o: In function `create':
/home/windea/workshop/ricm4/as/nanvix/src/kernel/sys/sem.c:12: undefined reference to `semget'
/home/windea/workshop/ricm4/as/nanvix/src/kernel/sys/sem.c:17: undefined reference to `semctl'
sys/sem.o: In function `down':
/home/windea/workshop/ricm4/as/nanvix/src/kernel/sys/sem.c:25: undefined reference to `semop'
sys/sem.o: In function `up':
/home/windea/workshop/ricm4/as/nanvix/src/kernel/sys/sem.c:33: undefined reference to `semop'
sys/sem.o: In function `destroy':
/home/windea/workshop/ricm4/as/nanvix/src/kernel/sys/sem.c:41: undefined reference to `semctl'
makefile:67: recipe for target 'all' failed
make[2]: *** [all] Error 1
And finally, the last command line executed by make before the error was:
i386-elf-ld -T arch/x86/link.ld arch/x86/utilities.o arch/x86/io.o arch/x86/boot.o arch/x86/hooks.o arch/x86/setup.o arch/x86/hwint.o arch/x86/8259.o arch/x86/exception.o arch/x86/clock.o arch/x86/hal.o dev/dev.o dev/ata/ata.o dev/klog/klog.o dev/ramdisk/ramdisk.o dev/tty/console.o dev/tty/keyboard.o dev/tty/tty.o fs/file.o fs/block.o fs/super.o fs/buffer.o fs/pipe.o fs/inode.o fs/fs.o init/main.o lib/kstrncpy.o lib/kpanic.o lib/kprintf.o lib/kvsprintf.o lib/krand.o lib/kmemcpy.o lib/ksrand.o lib/kmemdump.o lib/kstrlen.o lib/kstrcmp.o lib/kstrcpy.o lib/kmemset.o lib/kstrncmp.o lib/bitmap.o mm/mm.o mm/paging.o mm/region.o pm/die.o pm/sleep.o pm/pm.o pm/sched.o pm/signal.o sys/times.o sys/stat.o sys/setgid.o sys/alarm.o sys/shutdown.o sys/kill.o sys/chmod.o sys/ioctl.o sys/umask.o sys/close.o sys/_exit.o sys/ustat.o sys/setegid.o sys/getgid.o sys/fork.o sys/getpgrp.o sys/nice.o sys/chroot.o sys/brk.o sys/syscalls.o sys/ps.o sys/wait.o sys/sync.o sys/unlink.o sys/setpgrp.o sys/signal.o sys/pause.o sys/link.o sys/read.o sys/gticks.o sys/fcntl.o sys/utime.o sys/write.o sys/geteuid.o sys/chdir.o sys/pipe.o sys/getegid.o sys/setuid.o sys/access.o sys/execve.o sys/getppid.o sys/chown.o sys/uname.o sys/lseek.o sys/sem.o sys/open.o sys/seteuid.o sys/getuid.o sys/getpid.o -o /home/windea/workshop/ricm4/as/nanvix/bin/kernel
I have no idea if this will help anyone to understand my issue, but now I think you can have a better grasp of what's going on at least.
Looks like you are compiling only the main.c and not fun1.c, fun2.c and fun3.c
You can try to compile as follows:
gcc -c main.c -o main.o
gcc -c fun1.c -o fun1.o
gcc -c fun2.c -o fun2.o
gcc -c fun3.c -o fun3.o
gcc main.o fun1.o fun2.o fun3.o -o all.out
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!
I have 3 .c files main.c, fun1.c, fun2.c
char buff[50];//in fun1.c
char *arg; //in fun2.c
arg = strstr(buff, "001"); //in fun2.c
I want to print buff in fun2.c but it gives an error buff undeclared, even though I declared it in fun1.h as extern char buff[];
There are functions in fun1.c and fun2.c each
It is hard to say what is wrong with your particular program, but here is an example which links 2 .c files with one .h file.
1. A header file functions.h:
#include <stdio.h>
extern void func();
Where I use extern to provide definitions for another file.
2. Now, a functions.c file which uses this header file:
#include "functions.h"
void func() {
printf("hello");
}
This needs to #include the header file, and use the function void() to print a message.
3. Finally, a main.c file which links it all together:
#include <stdio.h>
#include <stdlib.h>
#include "functions.h"
int main(void) {
func();
return 0;
}
Which also needs function.h as it uses func(). You then can compile the code as:
gcc -Wall -Wextra -g main.c functions.c -o main
You could also look into makefiles, which would reduce this long compilation line to simply make.
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".
I am trying to link two files. Means, there are files "file1.c" and "file2.c".
file1.c
#include"stdlib.h"
#include"stdio.h"
void function1(int a)
{
printf("hello I am file%d.c\n ", a);
}
void main()
{
function1(1);
}
file2.c
#include"stdlib.h"
#include"stdio.h"
#include"file.h"
void function2(int b)
{
printf("hello I am file%d.c\n", b);
}
int main()
{
function2(2);
function1(1);
}
Then I make a header file file.h as
#ifndef hell
#define hell
void function1(int a);
#endif
When I compile file2.c as "gcc file2.c file1.c -o file2
" it gives following error
/tmp/cc4tno9R.o: In function `main':
file1.c:(.text+0x24): multiple definition of `main'
/tmp/ccL4fEki.o:file2.c:(.text+0x24): first defined here
collect2: ld returned 1 exit status
How to write in header file? Is there any error in header file?
Or error in file2.c?
And what about extern? Is it uses for same purpose?
Say that the directory structure is like:
Project
|
------------------------------
| | |
csource output header
| | |
*.c files executable .h files
files
Now, put these two .c files inside the source folder.
function.c
int sum(int a, int b)
{
return (a + b);
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <mymath.h>
int main(void)
{
int result = sum(11, 19);
printf("Result: %d\n", result);
return EXIT_SUCCESS;
}
Put this header file inside header folder.
mymath.h
#ifndef _MyMath_H__
#define _MyMath_H__
int sum(int, int);
#endif
COMPILATION:
Firstly, we will compile function.c file and create one object file with .o extension, as follows:
C:\Mine\C\test\project>gcc -o output\function.o -c source\function.c
On Cygwin:
Gagandeep Bali#LAPTOP ~/c/Mine/C/test/project
$ gcc -o output/function.o -c source/function.c
Since, function.c doesnot contains a main method, hence, we will simply use the -c option, to only create an object file.
Here, the use of -I option, basically tells the compiler, where to look for include files. Since, we are defining our header folder, hence, you can use #include <mymath.h> instead of #include "mymath.h". Now we will compile themain.c` file as:
C:\Mine\C\test\project>gcc -o output\main -I header\ -Wall source\main.c output\function.o
On Cygwin:
Gagandeep Bali#LAPTOP ~/c/Mine/C/test/project
$ gcc -o output/main -I header/ -Wall source/main.c output/function.o
Now one can run it, like:
C:\Mine\C\test\project>.\output\main
Result: 30
On Cygwin:
Gagandeep Bali#LAPTOP ~/c/Mine/C/test/project
$ ./output/main
Result: 30
You can also, create static and dynamic libraries, of custom functions, that you can use. I just know, how to create a static library.
If you wanted to create a static library, of your own, simply first put all object files inside the library. Create another folder, say library for this purpose. Now add all .o files inside the library, like this:
Gagandeep Bali#LAPTOP ~/c/Mine/C/test/project
$ ar cr library/mymathlibrary.a output/function.o
Now simply compile program like:
Gagandeep Bali#LAPTOP ~/c/Mine/C/test/project
$ gcc -Wall source/main.c library/mymathlibrary.a -o output/main -I header
And run as previously described.
You don't need to include all library files in the first file. Just save it as a library file with a ".h" extension as a library file and include it in second file, Like shown below.
file1.h
void function1(int a) {
printf("hello I am file%d.c\n ", a);
}
file2.c
#include <stdlib.h>
#include <stdio.h>
#include "file.h"
void function2(int b) {
printf("hello I am file%d.c\n", b);
}
int main() {
function2(2);
function1(1);
return 0;
}
So all should look like this:
file1.c:
#include <stdlib.h>
#include <stdio.h>
void function1(int a) {
printf("hello I am file%d.c\n ", a);
}
file2.c:
#include <stdlib.h>
#include <stdio.h>
#include "file.h"
void function2(int b) {
printf("hello I am file%d.c\n", b);
}
int main() {
function2(2);
function1(1);
return 0;
}
When you run the program main is beeing called. If you have 2 definitions of main which one should be called?
There should be one file including main and another file including function that you want to use in the first file.