How to declare DLL in user32.dll (aka stdcall?) fashion? - c

I have a third party application that allows you to call C functions from DLL files. Provided sample to this app shows you can call MessageBoxW from user32.dll. It also allows you to call C functions from your DLL files.
I've did a DLL from a file.h file like this:
_declspec (dllexport) void example(int);
and file.c like this:
#include <stdio.h>
#include "file.h"
_declspec (dllexport) void example(int s1)
{
printf("dsa");
}
And compile it with C/C++ Compiler Version 15 from Windows SDK like this:
cl file.c /DLL /LD
And i get proper compilation with DLL file. In DLL functions examiner I see my function. I drop this file into System32 folder and call it from this third party application.
Application finds the file, but is unable to find the function.
I think the cause of the problem is that i declare (or compile) my DLL in other fashion/way/standard that Windows libraries (like user32.dll) because user32.dll works fine.
I've found that the third party app uses this kind of calling functions in DLL:
winapi_abi Used for calling Windows system functions. These are
declared as stdcall on Windows, but do not have mangled names.
So my question is: how to prepare and compile DLL file in the user32.dll fashion (stdcall?) so it will work with third party app?

The easy answer is:
__declspec(dllexport) void __stdcall example(int);
And the same in the implementation, of course.
If you look into windows.h and friends you'll see:
#define WINUSERAPI __declspec(dllexport)
#define WINAPI __stdcall
And then:
WINUSERAPI int WINAPI MessageBoxW(HWND,LPCWSTR,LPCWSTR,UINT);
But if you just define a few functions there is no need for the macros.

Include a .def file to defeat stdcall name decoration. Then you can get rid of the __declspec(dllexport) clutter.

You are not specifying any calling convention in your function declaration, so the compiiler will default to __cdecl, which decorates the exported name. Also, if you compile in C++ instead of C, additional decorating occurs as well. You need to do something like the following in your code to get around all of that:
file.h:
#ifndef fileH
#define fileH
#ifdef _BUILDING_DLL_
#define MYEXPORT __declspec (dllexport)
#else
#define MYEXPORT __declspec (dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
MYEXPORT void __stdcall example(int);
#ifdef __cplusplus
}
#endif
#endif
file.c:
#include <stdio.h>
#define _BUILDING_DLL_
#include "file.h"
void __stdcall example(int s1)
{
printf("dsa");
}

Thank you all. The solution was to add def file with exports, include it in compiler by /DEF:file.def, use Remy version (without #define _BUILDING...) and remove _stdcall.

Related

__declspec(dllexport) while importing. Does not seem to make a difference?

Let me begin by saying, I know what the purpose of the __declspec(dllexport) keyword is. But experimenting for the sake of it, when importing functions with this keyword vs when not using the keyword, I don't see any difference in the import/export table of the EXE that gets generated.
To illustrate, I have a DLL project that includes a header file with the following declaration:
__declspec(dllexport) int somefunc(int, int)
And then another project that builds an EXE importing functions from the DLL:
#include "path_to_header_file_of_dll"
int main() {
somefunc();
}
When I build this EXE, it seems to compile and build fine even though I have declared the function as exporting that symbol, when it is clearly not exporting it, only importing it. Why doesn't the compiler complain? Also this doesn't cause the generated EXE to have an export table. But builds an import table instead. The compiler seems to have figured out the correct thing to do and does it.
If this works, then why bother with code like this below:
#ifdef BLEH
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
DLLEXPORT int somefunc(int, int);

function definition in header file(c using gcc)

I am writing a simple c test framework. For simplicity, I only provide a single header file (containing all the function definitions), but I meet some problems. If I only include the header once, everything works fine. If I include the header twice, the gcc linker report duplicate symbol error (that is normal), so I add static prefix in every function in the header. This time it works, but the function is duplicate in the final binary. See bellow:
[heidong#HEIDONGVM ztest]$ nm m | grep __ct_hex_dump
0000000000400904 t __ct_hex_dump
0000000000401efc t __ct_hex_dump
Is there some way the made the function define only once?
Thanks a lot!!
Maybe someone needs the code, I just started a project in github: https://github.com/buf1024/test
Thanks again!!
What you have is in ct.h
static functions
static function definitions
In atest.c
// This is the first lot of definitions
#include "ct.h"
In main.c
// This is the second lot of definitions
#include "ct.h"
To fix
move the static function definitions to ct.c, remove the word static
Change all the prototypes in ct.h from static to extern
add ct.c to your link.
Edit: just delivering just ct.h
Change all the prototypes in ct.h from static to extern
Before the first function body add #ifdef __CT_C__
After the last function, add #endif
Tell the user that in the code that contains main, they need to #define __CT_C__ before they #include "ct.h"
Anything else that #include "ct.h" must not define __CT_C__.
Use compiler directives.
#IFNDEF MYFUNC
#DEFINE MYFUNC
myfunc();
#ENDIF
Everytime the compiler hits this directive, it will only go in once when MYFUNC is not defined and after defining it, it won't go in the statement again. No matter how many times you include the header file, it will always check if it's been defined before.
Coppiler directives is not part of the compiled code. It's just a directive.
If you absolutely need only one file, you can do it with preprocessor:
header.h
#ifndef HEADER_H
#define HEADER_H
#ifdef IMPLEMENT
#undef IMPLEMENT
void func(void) {
...
}
#else
void func(void);
#endif
#endif
In one file:
// Define
#define IMPLEMENT
#include "header.h"
In other files:
// Only declarations
#include "header.h"
Though I would choose a proper .c file instead.

What are the exact steps for creating and then linking against a Win32 DLL on the command line?

Here's my library Lib.c file:
#include <stdio.h>
int helloworld(){
printf("Hello World DLL");
}
Here's my exe Main.c file:
int helloworld();
int main(int argc, char** argv){
helloworld();
}
I would like to create Lib.dll, and Main.exe, where Lib.dll comes from Lib.c and Main.exe links against Lib.dll.
What are the specific steps to achieve this?
See this related question on how to build the DLL.
Your library code as it stands does not export any symbols and your executable does not import the symbols from your library. Two typical patterns for doing that are shown below but you might want to read up on that first.
The first method uses __declspec() to declare in the code what functions (or other items) are exported from your DLL and imported by other executables. You use a header file to declare the exported items and have a preprocessor flag used to control whether the symbols are exports or imports:
mylib.h:
#ifndef MYLIB_H
#define MYLIB_H
#if defined(BUILDING_MYLIB)
#define MYLIB_API __declspec(dllexport) __stdcall
#else
#define MYLIB_API __declspec(dllimport) __stdcall
#endif
#ifdef __cplusplus
extern "C" {
#endif
int MYLIB_API helloworld(void);
#ifdef __cplusplus
}
#endif
#endif
I have also specifically set the calling convention to __stdcall as are most DLL functions (I could have used WINAPI instead of __stdcall if I had included windows.h) and have declared the functions as extern "C" so their names do not get mangled when compiled as C++. Not such a problem here as it's all C, but if you were to build the DLL from C source and then try to use it from a C++ executable then the imported names would be incorrect.
The code could then look like this:
mylib.c
#include "mylib.h"
#include <stdio.h>
int MYLIB_API helloworld(void)
{
printf("Hello World DLL");
return 42;
}
You'd build your DLL using the following command line. As well as creating the DLL it will create the import library (.lib) required to use your DLL from another executable (as well as the export file, but that is only required in certain circumstances):
cl /DBUILDING_MYLIB mylib.c /LD
The /DBUILDING_MYLIB argument defines the preprocessor symbol used to control whether the functions in the DLL are exports (if it is defined) or imports (not defined). So you'd define it when building the DLL but not when building your application.
The /LD parameter tells cl to produce a DLL.
The second method is to use module definition files as mentioned in the comments. You can use the code you already have but you also need to create the module definition file. At it's simplest it looks like this:
LIBRARY mylib
EXPORTS
helloworld
In this case to build the DLL you require the following command line:
cl /LD mylib.c /link /DEF:mylib.def
You could then code your application so that it used your library header with the imported version of your DLL function:
main.c
/* No need to include this if you went the module definition
* route, but you will need to add the function prototype.
*/
#include "mylib.h"
int main(void)
{
helloworld();
return (0);
}
Which you could then compile with the following command line (assuming the import library from the DLL creation is in the same directory as your main.c). This step is the same whether you used declspec or module definition files:
cl main.c /link mylib.lib
Arguments passed after the /link argument are passed onto the linker command line as they appear, so as just a filename it is used as extra input to link into the executable. In this case we specify the import library generated when we built the DLL.
The command lines I've shown here are pretty much the absolute minimum you'd need but it'll allow you to create a DLL and link an application to it.
I have assumed the calling convention is correct in all of the above and I have not experimented much to see whether I got it wrong at any point.

Unable to resolve symbol when using lib... any ideas?

Written in C (into a C++ project):
I have two projects in VS08 under the same solution. One is a DLL file and the other ("runner") is the a console application for using/testing the DLL file. The header file has a header file with all the functions (__declspec(dllexport)). When I use functions without any arguments, by the runner console application, they run OK. When I try to call a function with arguments I get unable to resolve symbol... error. The strange thing is that VS08 recognizes the function and I can open it from the runner main() with the right-click menu, however it can't find it.
Worth mentioning that I am including the header file and not importing the DLL with function pointers... My feeling is that the functions get renamed somehow in the compiling process and the linker can't find the functions with the arguments. If I would be able to to see the list of new names (inside the object file?) maybe I could include them in the header file to fix this?
Thanks.
Written in C (into a C++ project):
That's possibly a pretty good lead. A C program cannot consume functions that were written in C++. When you use __declspec(dllexport), the function gets exported with its C++ name. Which is decorated by the compiler, a trick to allow overloaded functions to link properly. A C compiler doesn't apply the same kind of decoration, the linker will complain that it can't find the function.
To make this work, you have to declare the function with the extern "C" declarator. Make the .h file look like this:
#ifdef __cplusplus
extern "C" {
#endif
#undef DLLEXPORT
#ifdef BUILDING_MYDLL
# define DLLEXPORT __declspec(dllexport)
#else
# define DLLEXPORT __declspec(dllimport)
#endif
DLLEXPORT void Foo(int arg);
// etc..
#ifdef __cplusplus
}
#endif
In your DLL project, use Project + Properties, C/C++, Preprocessor and add BUILDING_MYDLL to the Preprocessor Definitions settings.
A short explanation for this macro madness: the #ifdef __cplusplus ensures that all the DLL declarations are declared extern "C" when they are compiled by the C++ compiler so that they'll match the C compiler symbols. The DLLEXPORT macro ensures that the functions are exported when you build the DLL, imported when you link the DLL import library in another project.
You can get additional troubleshooting from the dumpbin.exe utility by running it with the /exports option on your DLL. It shows the exact names of exported functions. Run it from the Visual Studio command prompt. A mismatch between the names you see in the output verses the linker error messages is a sure sign of trouble.
First off: Intellisense finding it ('open for the rightclick menu' eeeeck?) is no proof; it proves you put the declaration in a header file;
You are probably right about the name mangling thing: If you have C externals you need to declare them inside an extern "C" {} block:
extern "C" {
void dostuff(int param1, char* param2);
}
instead of
extern void dostuff(int param1, char* param2);
The most flexible approach is probably to include the extern "C" around the complete C header file conditionally:
// Sample.h
#if defined(__cplusplus)
extern "C"
{
#endif
// Function declarations
#if defined(__cplusplus)
}
#endif
See MSDN for more info

dllimport /dllexport and static libraries compilation under visual c++

I desperatly need your help.
Im trying to compile statically the poppler library (specially for qt4) on windows with the visual c++ 2008 compiler. To achieve this task I needed to compile a bunch of other libraries as dependencies for poppler statically too. When I finally generate the static version of poppler I got a linking error when building my app:
error LNK2019: unresolved external symbol "__declspec(dllimport)...
I already added the new include path and linked the poppler-qt4.lib but i get the error anyways.
Searching for a solution I found this discussion here in stackoverflow
How to link a static library in Visual C++ 2008?
whit this information I looked on the include files of the libraries (dependencies of poppler like zlib, libpng, cairo, ...) and I found, in various cases, that they don't have a preprocessor directive to especify the static version of the lib.
Example static directive (openjpeg.h):
#if defined(OPJ_STATIC) || !(defined(_WIN32) || defined(WIN32) || defined(__WIN32__))
# define OPJ_API
# define OPJ_CALLCONV
#else
# define OPJ_CALLCONV __stdcall
# ifdef OPJ_EXPORTS
# define OPJ_API __declspec(dllexport)
# else
# define OPJ_API __declspec(dllimport)
# endif /* OPJ_EXPORTS */
#endif /* !OPJ_STATIC || !WIN32 */
Example without static directive (jconfig.h from jpeg lib):
#if defined(_WIN32)
#if defined(libjpeg_EXPORTS)
#define JPEG_EXPORT __declspec(dllexport)
#else
#define JPEG_EXPORT __declspec(dllimport)
#endif
#else
#define JPEG_EXPORT
#endif
My question is: Is not enough to change the properties of the project from dynamic to static so I have to change this headers too?, and if this is true, where can I define this new directives for making a difference between static or dynamic compilation?
Thanks in advance.
First please note Windows does not have any dynamic linkage at all. Surprise! Instead, it uses thunks. So what happens is: if you make a symbol dllexport, it has its actual name, the same name as if it were not dllexport. However it is marked in the object file for exporting.
If you say dllimport, on the other hand, the name is changed, in C roughly by prepending __imp_ to the name, more nasty in C++.
Now, when you link a DLL, you get a DLL (of course) but you also get a LIB file. That is a static link library. Which is the only kind the linker can handle. For each symbol exported from the DLL there is a dllimport symbol in that LIB file, in particular with __imp_ prefix or whatever for C++.
So now in a program or DLL you want to link to that DLL you made you link instead against the import LIB. The import LIB routines are thunks that patch up to the actual load time addresses from the DLL.
So now, if you try to do ordinary static linkage against a LIB file made by LIB.EXE by simply combining OBJ files which contained some dllexport, it will fail if the reference is a dllimport. Because you're refering to __imp_function() when the library actually contains plain function().
So with static linkage, you have to drop the dllimport. AFAIK dllexport is irrelevant. Note that this applies to the client of the library, not the library itself.
What does that mean? Well it is perfectly fine to statically link to a library which in turn dynamically links to another library. In fact by default static links on Windows dynamically link to the C runtime and OS DLLs. So the rule is: the client must chose the method of linking to a library, the provider should provide both versions. But take care they have different names!! (Otherwise the LINK making the DLL will make fred.LIB and the LIB will also make fred.LIB)
If you are changing the project properties from dynamic to static linkage as specified in the openjpeg.h you have to specify preprocessor that can use the static linkage..so in addition to changing the property from dynamic to static, add the preprocessor OPJ_STATIC...
For example:
#if defined(_WIN32)
#if defined(OPJ_STATIC)
# define OPJ_CALLCONV __stdcall
#el if defined(libjpeg_EXPORTS)
#define JPEG_EXPORT __declspec(dllexport)
#else
#define JPEG_EXPORT __declspec(dllimport)
#endif
#else
#define JPEG_EXPORT
#endif

Resources