undefined reference to 'CreateSemaphoreEx' when compiling with gcc on Windows - c

I am trying to compile some WinAPI code using gcc compiler.
However whenever I call functions like CreateSemaphoreEx, CreateMutexEx (and some other Ex functions) I get
"undefined reference to 'CreateSemaphoreEx'" link error.
It works with CreateSemaphore or CreateMutex but not the Ex versions of these functions.
First I compiled with mwindows flag as such (gcc main.c -mwindows)
Then I tried linking to the library manually (gcc -lkernel32 main.c)
I have also tried using CreateSemaphoreExA
I also tried uninstalling and reinstalling mingw-w64 and even tried switching to TDM-GCC
I know if I change it to CreateSemaphore call it works, however I want to use the Ex version.
#include <windows.h>
int main(int argc, char** argv)
{
int initial_count = 0;
int maximum_count = 5;
HANDLE semaphore = CreateSemaphoreEx(0, initial_count, maximum_count, NULL, 0, SYNCHRONIZE | SEMAPHORE_MODIFY_STATE);
}
How can I get access to these WinAPI functions using gcc compiler on Windows (if it is at all possible).
-------- Complete Compiler Output ---------
main.c: In function 'main':
main.c:8:21: warning: implicit declaration of function 'CreateSemaphoreEx'; did you mean 'CreateSemaphoreA'? [-Wimplicit-function-declaration]
HANDLE semaphore = CreateSemaphoreEx(0, initial_count, maximum_count, NULL, 0, SYNCHRONIZE | SEMAPHORE_MODIFY_STATE);
^~~~~~~~~~~~~~~~~
CreateSemaphoreA
main.c:8:21: warning: initialization of 'HANDLE' {aka 'void *'} from 'int' makes pointer from integer without a cast [-Wint-conversion]
C:\Users\Nexwave\AppData\Local\Temp\cc3ncRYX.o:main.c:(.text+0x49): undefined reference to `CreateSemaphoreEx'
collect2.exe: error: ld returned 1 exit status
Edit 1:
I know about linking.
My question is whether the kernel32 library used by mingw-w64 different than one used by Microsoft's linker.
And if it is different then why is there no definition for CreateSemaphoreEx (and some other Ex functions) that are available in the actual Kernel32.lib

The problem indicated by the first diagnostic:
implicit declaration of function 'CreateSemaphoreEx'
The other errors are cascading from that. In general you should always fix the first compiler diagnostic before worrying too much about the others.
Note, I would recommend using standard compiler switches so that it says "error" instead of "warning" for this error condition, and breaks compilation. Some people see the word "warning" and think "oh it's just a warning and not important, I'll ignore it" but that would be a mistake in this case.
The error message above means that your system headers do not define CreateSemaphoreEx. Why is this? Here are the main possibilities:
You're on an old version of Windows; the function was added in Windows Vista and will not be accessible if you're on XP for example. (The Windows headers don't define the prototype and macro if the system is detected as being pre-Vista).
You're using an old version of mingw-w64 that doesn't have this function.

Related

Const in C function declaration and implementation

I have a function declared in code.h and implemented in code.c.
it goes like:
void someFunc(const char*);
and
#include "code.h"
void someFunc(const char* str){ printf("%s\n", str); }
Now I found out I can remove the const in any one of the files (leaving it there in the other) and it compiles & runs with no errors.
I wonder what's the meaning of this?
Is one of the files the only one that matters?
It might sound like just an unimportant niche behaviour, but this fact means that a missed const can go unnoticed.
What happens if declaration and definition of a function don't agree on whether an argument is const or not?
You should get a compilation error.
What to do?
Update your compiler.
With gcc 4.2.1, I am receiving an error, if I remove const from either the header or the source file:
Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c code.c
code.c:3:6: error: conflicting types for 'someFunc'
void someFunc(const char* str){ printf("%s\n", str); }
^
./code.h:1:6: note: previous declaration is here
void someFunc(char*);
^
1 error generated.
With gcc version 4.9.2 (Debian 4.9.2-10), I am getting the same behavior.
Same behavior with gcc's 7.1.0 version, online in Wandbox:
My guess is that the behavior your are experiencing is architecture/compiler's version dependent.
In C, a diagnostic is required if function declaration and function definition are both visible to the compiler, and don't match.
If your compiler is actually a C++ compiler, the declaration and definition need not match - since they will be considered overloads. However, if both overloads are not defined, there will be linker errors (compilation units call the overload they see a declaration for, and linking fails since that function is not defined).
Other compilation units which have visibility of the declaration from the header but not of the definition will compile if arguments being passed are correct, and fail otherwise. In both C and C++.
If your code consistently builds and runs, then your compiler is not behaving in a standard way (e.g. compilation options that make it not comply in this regard). Or there is some problem with the build process (such as an object not being rebuilt if a header or source file it depends on changes - which means the executable corresponds to an older version of your source).

why c doesn't check for return statements at compilation

I have started learning c. If a function is not called why compiler doesn't catch it as an error.
int foo(){}
void main(){}
I know it is a silly thing but could not figure it out.
If a function isn't called, that function will be doing nothing, and won't hurt to sit there. Also, sometimes you want to make libraries of functions, and these will not be called from anything in the compiled code, but may be called from other executables or libraries. The compiler will not know anything about this at compile-time.
There's probably a warning you can switch on on your compiler though.
You compiler doesn't know that your function isn't used, so it can't warn you about it. It's possible that in another file you declare this function and use it. The linker would then resolve it to this file after compilation.
On the other hand, if you enable warnings (e.g. by passing -Wall to the compiler), it will warn you of possible problems whenever possible.
For example if I compile your code with clang -Wall yourcode.c I get :
yourcode.c:1:11: warning: control reaches end of non-void function [-Wreturn-type]
int foo(){}
^
yourcode.c:2:1: warning: return type of 'main' is not 'int' [-Wmain-return-type]
void main(){}
^
yourcode.c:2:1: note: change return type to 'int'
void main(){}
^~~~
int
2 warnings generated.
So as you can see, the compiler will tell you if you forget a return or write a bad main, as long as you enable warnings. But with the code you posted, it can't tell you about functions that aren't used.
If you want the compiler to warn you about unused functions, you should declare those functions static, this will mean that those functions will only be usable in the file where they are defined. Then the compiler can tell you if you don't use it and you'll get a warning like this one :
yourcode.c:1:12: warning: unused function 'foo' [-Wunused-function]
static int foo(){}

Get the current working directory in C on windows

For some bizarre reason, when I try to use the function get_current_dir_name with MinGW GCC compiler,
I get this result on linkage:
undefined reference to `get_current_dir_name'
collect2.exe: error: ld returned 1 exit status
But, I get this only when using the function like this
printf("%i", get_current_dir_name());
or this
printf("%s", get_current_dir_name());
When I try to do
printf(get_current_dir_name());
I get this, which makes no sense, because the function returns a char *, according to docs:
tester.c: In function 'main':
tester.c:16:2: warning: passing argument 1 of 'printf' makes pointer from integer without a cast [enabled by default]
printf(get_current_dir_name());
^
In file included from tester.c:1:0:
c:\mingw\include\stdio.h:294:37: note: expected 'const char *' but argument is of type 'int'
_CRTIMP int __cdecl __MINGW_NOTHROW printf (const char*, ...);
Google seem to really dislike talking about C, because I can find how to get the workdir on almost any existing language, except C. The only thing that pops up are some docs, which describe 3 functions: getcwd, getwd, and get_current_dir_name. I really want to use the get_current_dir_name one because of it's cleanness.
How do I deal with this? Is this a minGW bug? Or am I missing something?
You apparently failed to include any header that contains a declaration of get_current_dir_name(). Thus, the compiler will assume a return value of int, which is not a valid first argument for printf() (you should increase the warning levels so you'll get an error instead of just a warning).
Furthermore, linking fails, so you also do not link against a library that implements the function, which is expected: get_current_dir_name() is a GNU extension and not part of the C standard library.
On Windows, you need to use the equivalent functionality provided by the Windows API, ie GetCurrentDirectory(), declared in windows.h.

Unexpected function prototype behavior in C

I was studying C from K & R and got confused in part 4.4 of the book, when it is referring to scope rules. Before I go any further, let me just post the source file I am working on.
#include <stdio.h>
void first(void);
int main(void) {
printf("In main.\n");
first();
second();
return 0;
}
void first(void) {
printf("In first.\n");
}
void second(void) {
printf("In second.\n");
}
Now, unless I am more stupid than I imagine, the book gave me the idea that function prototypes (in the same file as the definition of the function) exist for scoping reasons. That is, they exist to allow the function to be declared at the top of a compiled file to for the rest of a source file to be notified for the existence of an "object" if I may so call it, ahead of time.
My issue with the above code is that in an Arch Linux Virtual Machine I am working on with GCC version 4.7.1 the above file can NOT compile and gives the following error: conflicting types for second.
However, when the very same code is run into my physical machine, sporting Ubuntu 12.04 with GCC version 4.6.3 it compiles just fine.
My question is: Is this a compiler feature? Because if it is not, I am surprised it compiles at all, seeing as there is no function prototype for second, main (if I have understood it correctly) should not be able to know about second's existence.
The "conflicting types" error message happens because most C compilers, upon encountering a function that has not been declared yet, will implicitly declare a prototype for that function returning an int. So when second() is encountered in main(), GCC 4.7.1 is inferring the following definition:
int second();
Then when the compiler reaches the function definition, notices that the inferred prototype's signature does not match the definition's signature, and aborts with an error.
As far as why 4.6.3 successfully compiles this code, the following is a guess. GCC 4.6.3 may have some bug (or feature, you decide) that allows function implementations to differ from their prototypes by their return type. Since C allows functions with non-void return types to terminate without returning anything (which makes their return value undefined), this could simply be a case of two sub-optimal things canceling each other out.
(The behavior in 4.6.3 could also be a change in default compiler options between versions, or perhaps you are invoking the compiler with different options.)

mkdtemp requires _DARWIN_C_SOURCE for unistd.h

I am a little puzzled. I have project that I compile with
CFLAGS=-g -O2 -Wall -Wextra -Isrc/main -pthread -rdynamic -DNDEBUG $(OPTFLAGS) -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=700
Now I want to use mkdtemp and therefor include unistd.h
char *path = mkdtemp(strdup("/tmp/test-XXXXXX"));
On MacOSX the compilation gives some warnings
warning: implicit declaration of function ‘mkdtemp’
warning: initialization makes pointer from integer without a cast
but compiles through. While mkdtemp does return a non-NULL path accessing it results in a EXC_BAD_ACCESS.
Question 1: The template is strdup()ed and the result is non-NULL. How on earth can this result in an EXC_BAD_ACCESS?
Now further down the rabbit hole. Let's get rid of the warnings. Checking unistd.h I find the declaration hidden by the pre processor.
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
...
char *mkdtemp(char *);
...
#endif
Adding -D_DARWIN_C_SOURCE to the build makes all the problems go away but leaves me with a platform specific build. The 10.6 man page just says
Standard C Library (libc, -lc)
#include <unistd.h>
Removing the _XOPEN_SOURCE from the build makes is work on OSX but then it fails to compile under Linux with
warning: ‘struct FTW’ declared inside parameter list
warning: its scope is only this definition or declaration, which is probably not what you want
In function ‘tmp_remove’:
warning: implicit declaration of function ‘nftw’
error: ‘FTW_DEPTH’ undeclared (first use in this function)
error: (Each undeclared identifier is reported only once
error: for each function it appears in.)
error: ‘FTW_PHYS’ undeclared (first use in this function)
Question 2: So how would you fix this?
The only fix I have found is to #undef _POSIX_C_SOURCE right before the unistd.h include ...but that feels like an ugly hack.
You've asked two questions here, and I'm just going to answer the first:
Question 1: The template is strdup()ed and the result is non-NULL. How on earth can this result in an EXC_BAD_ACCESS?
As the warnings above tell you:
warning: implicit declaration of function ‘mkdtemp’
This means it couldn't find the declaration for mkdtemp. By C rules, that's allowed, but it's assuming the function returns an int.
warning: initialization makes pointer from integer without a cast
You've told the compiler "I've got a function that returns int, and I want to store the value in a char*". It's warning you that this is a bad idea. You can still do it, and therefore it compiles.
But think about what happens at runtime. The actual code you link to returns a 64-bit char*. Then your code treats that as a 32-bit int that it has to cast to a 64-bit char*. How likely is that to work?
This is why you don't ignore warnings.
And now for the second question:
Question 2: So how would you fix this?
Your problem is that you're explicitly passing -D_XOPEN_SOURCE=700, but you're using a function, mkdtemp, that isn't defined in the standard you're demanding. That means your code shouldn't work. The fact that it does work on linux doesn't mean your code is correct or portable, just that you happened to get lucky on one platform.
So, there are two rather obvious ways to fix this:
If you want to use _XOPEN_SOURCE=700, rewrite your code to only use functions that are in that standard.
If you've only added _XOPEN_SOURCE=700 as a hack that you don't really understand because it seemed to fix some other problem on linux, find the right way to fix that problem on linux.
It may turn out that there's a bug on one platform or another so there just is no right way to fix it. Or, more likely, you're using a combination of non-standard functions that can be squeezed in on different platforms with a different set of flags on each. In that case, your Makefile (or whatever drives the build) will have to pass different flags to the compiler on different platforms. This is pretty typical for cross-platform projects; just be glad you only have one flag to worry about, and aren't building 3000 lines worth of autoconf.

Resources