first of all I know this is asked a thousand times. But I opened a few and everyone forgot to compile/link it with it.
Anyway I created a linked list in a separate file with header and file, which works fine, however I tried to add a new function to it but then I have undefined reference to 'function.' Here is the source:
list.c
#include "list.h"
struct node
{
item_t x;
struct node *next;
};
struct node* root;
//Window hider extension
void ToggleVisibleList(HWND currentHwnd)
{
if (root == 0)
return;
struct node *conductor = root;
while (conductor != 0)
{
HWND hwnd = (HWND)conductor->x;
ShowWindow(hwnd, IsWindowVisible(hwnd) ? SW_HIDE : SW_SHOW);
conductor = conductor->next;
}
ShowWindow(currentHwnd, IsWindowVisible(currentHwnd) ? SW_HIDE : SW_SHOW);
}
//...Rest of the file
list.h
#ifndef LIST_H
#define LIST_H
#include <stdlib.h>
#include <windows.h>
//Window hider extension
void ToggleVisibleList(HWND currentHwnd);
//.. rest of the header
main.c
#include <windows.h>
#include <stdio.h>
#include <commctrl.h>
#include "list.h"
HWND currentHwnd;
//..
HHOOK hookKeyboard;
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
if (wParam == WM_KEYDOWN)
{
KBDLLHOOKSTRUCT* hookStruct = (KBDLLHOOKSTRUCT*)lParam;
if (hookStruct->vkCode == 'Z' && GetAsyncKeyState(VK_LCONTROL))
{
ToggleVisibleList(currentHwnd);
}
}
}
CallNextHookEx(hookKeyboard, nCode, wParam, lParam);
}
//..Rest of file
I compile using Mingw (OS: Windows 8 64-bit):
gcc -o hider.exe main.c list.c -mwindows
C:\Users\...\AppData\Local\Temp\cc6sCa17.o:main.c:(.text+0x4bc): undefined reference to `ToggleVisibleList'
collect2: ld gaf exit-status 1 terug
//Translation: ld return exit-status 1
EDIT: Tried swapping the file order.
I hope I didn't duplicate a question, I don't think so because I've tried 20 questions first. (And google.)
Regards
Answer: rebooted my computer and it compiled.
Total shot in the dark answer:
I suspect this might work (swap list.c and main.c in the compile order)
gcc -o hider.exe list.c main.c -mwindows
I suggest this because linking with libraries has similar behavior with gcc. But I've never observed this problem with file order.
Fromt the gcc man page (in regards to -l library)
It makes a difference where in the command you write this option; the
linker searches and processes
libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library
z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be
loaded.
Related
I creating a program in c language and i using the Visual Studio Code for the first time, my functions in the header files don't function. This is my code in main:
#include <stdio.h>
#include "PilhaDinamica.h"
#include "PilhaEstatica.h"
int main()
{
Pilha *p = criaPilha();
return 0;
}
And this is my .h file:
#ifndef PILHADINAMICA_H_INCLUDED
#define PILHADINAMICA_H_INCLUDED
typedef struct Nodo{
char info;
struct Nodo*prox;
} nodo;
typedef struct {
nodo * Topo;
} Pilha;
Pilha * criaPilha();
int pilha_vazia(Pilha *p);
void push(Pilha *p, char times);
char pop(Pilha *p);
#endif
This is my file with the functions:
#include "PilhaDinamica.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Pilha *criaPilha()
{
Pilha *p = (Pilha*) malloc(sizeof(Pilha));
p->Topo = NULL;
return p;
}
And this is shown in my output: "...\AppData\Local\Temp\ccmjk1nS.o:main.c:(.text+0xf): undefined reference to `criaPilha'
collect2.exe: error: ld returned 1 exit status"
what can i do to make it compile correctly?
As a general rule of thumb, header files (*.h) contains declarations (type, variable and function declarations) and source files (*.c) the definitions of those declarations.
At the compilation step, only source files will be compiled (because the definitions are there). A program or library creation is a 2 (actually more, like preprocessing and more but for simplicity we keep it at 2) step process:
creating object files
e.g. gcc -c -o object_file_name.o source_file_name.c
link those object files into an executable or static/shared library
e.g. gcc -o program_or_library_name object_file_1.o object_file_2.o ...
So, in your case you have to call the compiler two times for your source files (with the -c flag) and once to link those created object files into an executable.
Note: If you're using a different compiler other than gcc, have a look at the documentation on how to create object files and link them together.
I'm trying to compile a Win32 app with MinGW, whose code can be found here. The source code compiles into an object just fine, but when I try and link it, this happens:
> gcc -o bin\updown.exe obj\updown.o -s -lcomctl32 -Wl,--subsystem,windows
obj\updown.o:updown.c:(.text+0x3ac): undefined reference to `StringCbPrintfW'
collect2.exe: error: ld returned 1 exit status
The only time this function appears is in the following snippet:
#include <windows.h>
#include <commctrl.h>
#include <strsafe.h>
...
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) {
LPNMUPDOWN lpnmud;
UINT code;
switch(msg) {
...
case WM_NOTIFY:
...
const int asize = 4;
wchar_t buf[asize];
size_t cbDest = asize * sizeof(wchar_t);
StringCbPrintf(buf, cbDest, L"%d", value);
SetWindowText(hStatic, buf);
}
break;
...
}
...
}
Your project can define STRSAFE_LIB before including strsafe.h, and then link to strsafe.lib. Note that strsafe.h will use a #pragma comment(lib, "strsafe.lib") statement if STRSAFE_LIB is defined, but I don't know if that pragma works in MinGW or not, so you may have to link to the .lib manually.
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 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
I can compile DLLs properly using mingw and do the exports/imports stuff. What I am looking for is defining the dll onload function properly as you would in MS VC products. Google didn't turn up anything. Anyone have any ideas or a link to a tutorial?
Okay, so after some fiddling...it's working. For anyone else that is having issues here it is. My issues weren't related to compiling in instead of loading dynamically. It was a mash-up of a couple of tutorial/question/how-tos that got me to this point.
dll.c
#include <stdio.h>
#include <windows.h>
#include "dll.h"
//extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD Reason, LPVOID LPV) {
//This one was only necessary if you were using a C++ compiler
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// Code to run when the DLL is loaded
printf ("Load working...\n");
break;
case DLL_PROCESS_DETACH:
// Code to run when the DLL is freed
printf ("Unload working...\n");
break;
case DLL_THREAD_ATTACH:
// Code to run when a thread is created during the DLL's lifetime
printf ("ThreadLoad working...\n");
break;
case DLL_THREAD_DETACH:
// Code to run when a thread ends normally.
printf ("ThreadUnload working...\n");
break;
}
return TRUE;
}
EXPORT void hello(void) {
printf ("Hello\n");
}
dll.h
#ifndef DLL_H_
#define DLL_H_
#ifdef BUILD_DLL
/* DLL export */
#define EXPORT __declspec(dllexport)
#else
/* EXE import */
#define EXPORT __declspec(dllimport)
#endif
EXPORT void hello(void);
#endif /* DLL_H_ */
hello.c
#include <windows.h>
#include <stdio.h>
int main () {
/*Typedef the hello function*/
typedef void (*pfunc)();
/*Windows handle*/
HANDLE hdll;
/*A pointer to a function*/
pfunc hello;
/*LoadLibrary*/
hdll = LoadLibrary("message.dll");
/*GetProcAddress*/
hello = (pfunc)GetProcAddress(hdll, "hello");
/*Call the function*/
hello();
return 0;
}
when compiled with
gcc -c -DBUILD_DLL dll.c
gcc -shared -o message.dll dll.o -Wl,--out-implib,libmessage.a
gcc -c hello.c
gcc -o hello.exe hello.o message.dll
produces the expected output of
Load working...
Hello
Unload working...
Since mingw is just a windows port of GCC and associated tools, you can use GCC constructor and destructor attributes. These work for both shared and static libraries, and execute code before and after main is run, respectively. Additionally, you can specify multiple constructor and destructor functions per library.
static void __attribute__((constructor))
your_lib_init(void)
{
fprintf(stderr, "library init\n");
}
static void __attribute__((destructor))
your_lib_destroy(void)
{
fprintf(stderr, "library destroy\n");
}