I'm trying to test if standard library (kernel32.dll) have one of the function.
Code snippet for test:
extern void CreateProcessA (void);
int
main (void)
{
CreateProcessA ();
return 0;
}
The code compiles and links as follow:
cl /c test.c
link test.obj kernel32.lib
This code can be compiled well with Visual C++, but cannot link:
test.obj : error LNK2019: unresolved external symbol _CreateProcessA referenced in function _main
But function CreateProcessA does exists in kernel32.dll, you no?
How to link it properly?
P.S. I don't want to run this code, just check that function exists (if code compiles and links - function exists).
To see if the function exists, you use
dumpbin /exports kernel32.dll | findstr CreateProcess
You didn't even use the right prototype, so of course the linker can't find the correct function. The naming convention is completely off, and CreateProcess is really a macro (that expands to either CreateProcessA or W depending on UNICODE).
(You don't need to link against kernel32.lib explicitly as that's already done by default by cl.exe)
Instead of declaring the prototype yourself, #include <windows.h>.
Kernel32.dll exports the function as "CreateProcessA", note the missing leading underscore. The only way to convince the linker to use that export is by linking kernel32.lib, an import library supplied by the Windows SDK.
You'll then run into the next problem, the import library declares the export as _CreateProcess#40. This is a name decoration applied by the __stdcall calling convention. That calling convention was explicitly designed to catch your mistake, you didn't declare the function properly. The #40 part of the name indicates the number of bytes needed in the stack frame to pass the arguments.
So, to make it work you should #include <windows.h> to get the proper function declaration and link kernel32.lib to get the proper export name.
Right now you are declaring your own version of CreateProcess(). Since you did not provide the body (code), the linker doesnt know where to check to find the function to execute.
In order to call CreateProcess from kernel32.lib, you need to include the proper headers
#include <windows.h>
If the compiler doesnt know windows.h then probably Platform SDK for windows isnt installed correctly.
you will also need to link with the proper lib
#pragma comment(lib, "kernel32.lib")
You should also read the documentation about createprocess since it takes a gazillion of parametetrs
BOOL WINAPI CreateProcess(
__in_opt LPCTSTR lpApplicationName,
__inout_opt LPTSTR lpCommandLine,
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in BOOL bInheritHandles,
__in DWORD dwCreationFlags,
__in_opt LPVOID lpEnvironment,
__in_opt LPCTSTR lpCurrentDirectory,
__in LPSTARTUPINFO lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInformation
);
You should search for CreateProcess examples across the interwebs and maybe consider switching to c++ since you're on windows
For starters, put in a proper header file for the prototypes, <windows.h>, as this is a Windows source, add the kernel32.lib for your linker, remove that prototype as it is incorrect. Your main function is debatable as to whether you are creating a command line program or a windows program - if it is the latter, that should read 'WinMain'.
If you look in the MSDN for the function 'CreateProcess', scroll down and you will see the 'Library', that is the hint to tell you which library you need to link for it to work properly.
Hope this helps,
Best regards,
Tom.
I think this is a bad idea, but if you want to do it, you need to link with the kernel32.lib export library.
You must include windows.h in order to get the correct prototype:
#include <windows.h>
int
main (void)
{
CreateProcess(); // will cause warning due to incorrect parameter list
return 0;
}
Is there a particular reason you don't want to include windows.h?
Using MinGW one can use the "-mwindows" flag. Example:
gcc.exe -c -g -MMD -MP -MF build/Debug/MinGW-Windows/newmain.o.d -o build/Debug/MinGW-Windows/newmain.o newmain.c
gcc.exe -o dist/Debug/MinGW-Windows/hwprint_dll build/Debug/MinGW-Windows/newmain.o -mwindows
This will include stuff like gdi32.a, kernel32.a, user32.a and ws2_32.a.
Related
I'm working on an application which defines it's own printf() to get around differences between the different CRTs out there or because some other platforms don't have it.
When building the application with gcc this automatically seems to work and the custom printf is used instead of libc's one; if I understand it correctly this is because of the order in which object files/libraries appear in the link command or maybe because object files are always searched before CRT libs, correct?
I'd like to do the same using msvc. Just building the project gives the expected 'LNK2005: _printf already defined in printf.obj' because printf is also in msvcrtd.lib. Fair enough. I know about /NODEFAULTLIB but that excludes everything resulting in unresolved references for everything but printf. I scanned through the other linker settings but couldn't find anything which allows this (apart from /FORCE maybe, but the 'might produce an invalid executable' comment doesn't make it sound like a good idea). Also nothing in the module definition file docs; the latter got me thinking it might be possible to create a stub library which has all exports from msvcrt.lib except printf but that seems a brittle solution even if it works.
In the end the question is simple: how do I tell msvc's linker it should skip msvcrt's printf definition and use the one from my printf.obj instead. Basically /NODEFAULTFUNCTION:printf or so. Just an answer for one single executable is ok, though I'd also be interested to know if and how it can be done when building a dll instead where the custom printf is exported: how to tell the linker it should use the export from my .lib instead of msvcrt.lib?
edit simplest repo I could find: create a file main.c:
#include <stdio.h>
int main(int argc, char** argv)
{
printf("Hello");
return 0;
}
and a file printf.c:
int printf(const char *fmt, ...)
{
write(1, "ok\n", 3);
return 3;
}
For VS2013 (though the other versions might work as well): create a new empty C++ project and add both files then build. (For gcc: just gcc main.c printf.c and the resulting a.out prints 'ok')
The culptrit for VS is #include : without that it works ok but I have yet to find out if the original code allows getting rid of it in some way. But even if it does I'd still want to know if this can be solved at the link level.
I would like to know , if I have source file like this
#include <stdio.h>
int main()
{
printf("Hello world");
}
as I know header files contains only prototypes of functions. If it so how can my source file get the function printf ? If I don't include the source file where it has been declared?
thank you
The question is not clear, but there are 2 things which happen before a program gets created,
Compiling (requires prototypes / declarations)
Linking (requires definitions).
Header information is needed for knowing prototypes. Even this would compile fine:
int printf ( const char * format, ... );
int main()
{
printf("Hello world");
}
On linking there will be no issues because the printf function is found in the C standard library, so on linking it will look into the standard directories (of the compiler where the library is kept - bin/lib folder) and link the function.
The source only needs to know the prototype. The problem a programmer will have in this case:
int my_printf ( const char * format, ... );
int main()
{
my_printf("Hello world");
}
The above will compile, but when linking my_printf your code will not have a definition so it will give an error on linking.
Header file has the definitions declarations of the functions ( stdio.h has definition declaration for printf ). The actual function exists in the libraries and gets linked when you compile the code.
When it comes to using libraries, you include the header of the library in your code and you instruct the linker to link using the code files of that library(usually object files). For the standard libraries, the IDE usually instructs the linker to link to them by default.
Assuming you're using gcc as a compiler the standard libraries are linked by default and that is where the function definitions lie. If you'd like to see exactly which libraries are being linked you can pass gcc the -v option which will cause it to dump information about the default options it will use including the library paths and default libraries and object files that will be linked in.
If you give the -Wl,--verbose option, gcc will pass the --verbose to the linker which will dump exactly where it's looking for libraries, including both failed and successful searches
gcc -v foo.c -Wl,--verbose
The header file stdio.h would declare printf as an extern function, i.e., it is defined elsewhere. The compiler is happy as long as functions you use have a declaration. The linker is the one that resolves these dependencies.
A very useful thing to do when you start asking good questions like this is to play with some linker commands.
Assuming you're on *nix, once you have your executable file (lets call it foo), do:
ldd foo
You should see a list of libraries that were linked with while creating foo.
libc.so should be one among those. It contains the definition for printf among other things!
You can refer to this link to learn more
Is it possible to load a DLL with C and use its functions?
I am new in C, and I am trying to search some good references on the internet for this; but I can't find any.
Any help would be appreciated!
I am using GNU GCC in Code::Blocks on Windows 7, 64 Bit.
HMODULE hModule = LoadLibrary(<dll file name>) followed by GetProcAddress(hModule, <function name>) will do this job using the WinAPI.
An example could be found here.
I think you should investigate the LoadLibrary function.
http://msdn.microsoft.com/en-us/library/ms684175.aspx
Loads the specified module into the address space of the calling process. The specified module may cause other modules to be loaded.
Building a DLL using MinGW, here are some instructions:
First, you need to mark your functions for export, so they can be used by callers of the DLL. To do this, modify them so they look like (for example)
__declspec( dllexport ) int add2(int num){
return num + 2;
}
then, assuming your functions are in a file called funcs.c, you can compile them:
gcc -shared -o mylib.dll funcs.c
The -shared flag tells gcc to create a DLL.
For a free IDE which will automate all the flags etc. needed to build DLLs, take a look at the excellent Code::Blocks, which works very well with MinGW.
Also, see the article Creating a MinGW DLL for Use with Visual Basic on the MinGW Wiki.
I am trying to write a multi-threaded program in which I need to call the function crypt. But the compiler throws this warning. Also it doesn't recognize crypt_data as well. Any ideas?
You need to include appropriate header file. In this case crypt.h
#include <crypt.h>
Pre-process the source of your program, e.g. by running gcc -E in place of gcc -c. Look at the output to see if some/all/none of the crypt functions you expect are appearing in the declarations.
Declare the prototype for the function crypt (Forward declaration) Or include the header which has that.
I'm following the tuto:
http://zetcode.com/tutorials/gtktutorial/firstprograms/
It works but each time I double click on the executable,there is a console which I don't want it there.
How do I get rid of that console?
I tried this:
add_executable(Cmd WIN32 cmd.c)
But got this fatal error:
MSVCRTD.lib(crtexew.obj) : error LNK2019: unresolved external symbol _WinMain#16 referenced in function ___tmainCRTStartup
Cmd.exe : fatal error LNK1120: 1 unresolved externals
While using gcc directly works:
gcc -o Cmd cmd.c -mwindows ..
I'm guessing it has something to do with the entry function: int main( int argc, char *argv[]),but why gcc works?
How can I make it work with cmake?
UPDATE
Let me paste the source code here for convenience:
#include <gtk/gtk.h>
int main( int argc, char *argv[])
{
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_show(window);
gtk_main();
return 0;
}
UPDATE2
Why gcc -mwindows works but add_executable(Cmd WIN32 cmd.c) not?
Maybe that's not the equivalent for -mwindows in cmake?
add_executable(Cmd WIN32 cmd.c)
Tells CMake this is a Windows program, and it looks for WinMain instead of main. If you want to see the flags being used you can run make VERBOSE=1. The question might be how do you define WinMain for gtk apps? I know with Qt, you link in a library that defines it for you.
You can set these linker flags to have a main() entry point and no console:
SET(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} /subsystem:windows /ENTRY:mainCRTStartup")
For more info, see this answer for the linker flags, and this answer for how to set flags in cmake.
For CMake 3.13 and newer you can use
target_link_options(target PRIVATE "/SUBSYSTEM:WINDOWS" "/ENTRY:mainCRTStartup")
If you want your program to run in console mode (ie a main function), you have to specify it in your project's properties in MSVC. What you're using right now is a project in windowed mode (ie a WinMain function, which you don't have, hence the error).
But if you don't want to get the ugly console window, you want to use the windowed mode (ie transform your main function into a propper WinMain function). This way your normal window is all that will show.
edit: As an aside, you really shouldn't name your program "cmd", that's the name of Windows' command interpreter.
According to the CMake documentation for using the WIN32 flag with ADD_EXECUTABLE:
When this property is set to true the executable when linked on Windows will be created with a WinMain() entry point instead of of just main().This makes it a GUI executable instead of a console application. See the CMAKE_MFC_FLAG variable documentation to configure use of MFC for WinMain executables.
However, your program's entry point is main() and not WinMain(). What you should do, instead, is omit the WIN32 flag, but you need to link against libgtk. So, you would use TARGET_LINK_LIBRARIES:
FIND_PACKAGE(GTK2 2.6 REQUIRED gtk)
INCLUDE_DIRECTORIES(${GTK2_INCLUDE_DIRS})
LINK_DIRECTORIES(${GTK2_LIBRARIES})
ADD_EXECUTABLE(myprogramname source1 source2 ... sourceN)
TARGET_LINK_LIBRARIES(myprogramname ${GTK2_LIBRARIES})
While the accepted answer works for MinGW, it won't work for MSVC when you don't define a WinMain. No answer is cross-toolchain compatible IMHO.
Fix Subsystem
add_executable(my_exe WIN32 main.c)
basically passes -mwindows if MinGW compiler is used or /SUBSYSTEM:WINDOWS if MSVC. This sets the subsystem field in PE header of the generated executable to 2 i.e. IMAGE_SUBSYSTEM_WINDOWS_GUI. This instructs Windows to not provide a separate console window for this executable.
Fix Entry Point on MSVC
When MSVC receives /SUBSYSTEM:WINDOWS, its runtime expects1 a WinMain, not main, to be defined unlike MinGW's (which works with any one defined). If you want to continue to use main, fix the entry point:
target_link_options(my_exe PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/ENTRY:mainCRTStartup>
)
1: Yes, OS first calls C runtime and it's the C runtime which calls your executable's entry point
Fix Subsystem Per-config
add_executable(my_exe WIN32 ... internally sets the executable's WIN32_EXECUTABLE property. This gives another, more useful way to do it:
add_executable(my_exe main.c) # look ma, no WIN32!
set_target_properties(my_exe PROPERTIES WIN32_EXECUTABLE 1)
This is useful when you want to do it only for some configurations. I personally enable this only on Release builds, while having a console window on Debug builds is useful.
# No console window for non-debug builds
set_target_properties(my_exe PROPERTIES WIN32_EXECUTABLE
$<AND:$<PLATFORM_ID:Windows>,$<NOT:$<CONFIG:Debug,RelWithDebInfo>>>
)
Verify
# Generate Ninja files for GCC
cmake -B build_g -G "Ninja Multi-Config"
# Generate Visual Studio project and solution for MSVC
cmake -B build_v -G "Visual Studio 17 2022"
# Build with verbosity
cmake --build build_g --config Release -v
This should show the actual build commands with parameters in full verbosity. Useful to verify if -mwindows or /SUBSYSTEM:WINDOWS is passed for the right build configurations.