What does the code "DECLDIR __declspec(dllexport)" really do? - c

#ifndef _DLL_TUTORIAL_H_
#define _DLL_TUTORIAL_H_
#include <iostream>
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
extern "C"
{
DECLDIR int Add( int a, int b );
DECLDIR void Function( void );
}
#endif
What does the code DECLDIR __declspec(dllexport) really do?

In the Microsoft world, __declspec(dllexport) makes a function or class callable from outside the DLL.
When you create a DLL, by default, any functions defined within the DLL are only callable from that same DLL. You cannot call that function from an executable or a different DLL.
If you want your a function to be called from outside the DLL, you need to export it by adding __declspec(dllexport).
One way to think about it is that __declspec(dllexport) marks a function as being part of a DLL's public interface.
While you didn't ask about __declspec(dllimport) that is sort of the opposite. When calling a function in a different DLL, your DLL needs to know that it's part of a different DLL's public interface so it can properly handle the call (calling a function in a different DLL requires more complex code that calling a function in yourself).

It defines the DECLDIR macro constant to be __declspec(dllexport). dllexport is for exporting functions from DLLs. Here's a quote from this page:
These attributes explicitly define the
DLL's interface to its client, which
can be the executable file or another
DLL. Declaring functions as dllexport
eliminates the need for a
module-definition (.DEF) file, at
least with respect to the
specification of exported functions.
Note that dllexport replaces the
__export keyword.
If a class is marked
declspec(dllexport), any
specializations of class templates in
the class hierarchy are implicitly
marked as declspec(dllexport). This
means templates are explicitly
instantiated and its members must be
defined.
__declspec, by the way, is explained here.

Related

How to port 32-bit DLL definitions to 64-bit?

I have an Application and DLL project that I am trying to port to a 64-bit environment. I ran into an issue with the DLL module definition that would cause linker errors such as the following when compiled with a 64-bit configuration:
2>mylib.exp : error LNK2001: unresolved external symbol _func_a#4
2>mylib.exp : error LNK2001: unresolved external symbol _func_b#4
The header definition for these functions looks like:
#ifdef MYLIB_DEF
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
DLLEXPORT extern int variable;
DLLEXPORT int __stdcall func_a(int value);
DLLEXPORT int __stdcall func_b(int value);
And in the C source file, it starts with this:
#define MYLIB_DEF
#include "mylib.h"
DLLEXPORT int variable;
DLLEXPORT int __stdcall func_a(int value)
{
...
Now, for the trouble part. We have something like this for the module definition file:
LIBRARY mylib.dll
EXPORTS
variable DATA
_func_a#4
func_a#4=_func_a#4
func_a=_func_a#4
_func_b#4
func_b#4=_func_a#4
func_b=_func_a#4
This triggers the aforementioned errors. I understand that MSVC decorates functions when compiled with __stdcall and 64-bit builds don't use/support __stdcall so there are no decorations. I was able to create an alternate definition file that seems to work like this:
LIBRARY mylib.dll
EXPORTS
variable DATA
func_a
func_b
But, as this file was last touched 10 years ago, I don't know if I understand all the implications or reasoning behind the use of this file. Would something like that file be adequate for 64-bit builds. While our app is the primary user of our DLL, we do have others that interface to the DLL directly so I do not want to break any compatibility, however, we have zero users of a 64-bit version at the moment.
Do we need the definition file at all if we are using __declspec(dllexport) everywhere and not using ordinal exports?
Should we just drop it for 64-bit builds or does it provide any value?
Does dropping it from 32-bit builds as unneeded noise risk breaking any external users? From local testing, it does not seem to be required, but I am doing a full rebuild of the app and DLL.
Why does every function need two additional aliases? Is this standard practice for 32-bit builds? Is there a 64-bit equivalent we should be doing?
I've looked over Microsoft's documentation on the topic, but it says nothing about 64-bit builds versus 32-bit builds:
https://learn.microsoft.com/en-us/cpp/build/reference/exports?view=msvc-170

Hide dependent DLL functions

I am struggling to understand if I can prevent exposing certain function calls from within a DLL that I am building. The function calls I want to hide are calls that are exposed by sqlite3.dll which I am building into another DLL of my own making. sqlite3.dll exposes 5 functions, one of which looks like this in the header:
SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3*);
The macros at play here are defined earlier as:
/*
** Provide the ability to override linkage features of the interface.
*/
#ifndef SQLITE_EXTERN
# define SQLITE_EXTERN extern
#endif
#ifndef SQLITE_API
# define SQLITE_API
#endif
#ifndef SQLITE_CDECL
# define SQLITE_CDECL
#endif
#ifndef SQLITE_STDCALL
# define SQLITE_STDCALL
#endif
Now, I am building sqlite3.dll into my application by linking against sqlite3.lib and including sqlite3.h (the source of the prior code snippets).
I realize I may be able to play with those macros to achieve what I want.
I expose the functions in my own dll with:
/* module entry point */
int __declspec(dllexport) __stdcall load_properties(CAObjHandle context);
When I look at the functions available in the output of my build, I get my functions+5 functions from the sqlite library. All of the functions in sqlite that are exposed have the declaration structure similar to what I showed for close() above.
Is there a way I can hide the sqlite functions? Is it the .lib file that is causing the issue? That file was auto-generated so I am not sure what is in there.
I discovered the answer. The sqlite3.dll was incorrectly specified as a source of exports to the compiler. Removing the directive to export functions from sqlite3.dll corrected the issue.

How to detect that extern "C" is in effect

I am trying to find all places where #include is placed inside extern C block. Is is possible to check this using preprocessor? I would like to do add something like this to my header files:
#ifdef EXTERN_C_IS_IN_EFFECT
#error File included from extern "C" block!
#endif
I am also looking for other ways to fail compilation in such case, e.g. use some special attribute. I am using gcc 4.4.7.
I defined following macro and then use it in every header which needs protection against inclusion in extern C block:
#define ASSERT_NO_EXTERN_C void assert_no_extern_c(int); void assert_no_extern_c(double);
Maybe you can define 2 function prototypes with same name and different parameters. You will get warnings in case of extern "C" block. And it is allowed in C++.
That's not possible because the preprocessor runs before any syntactical analysis is done; that is, the preprocessor doesn't even know what extern "C" is and it's action cannot depend on the presence of such a directive either.
However, linkage specifications do nest, so instead of making sure the includer did not specify extern "C", you could place your header within an extern "C++" specification to make sure that it uses C++ linkage.

How do I create a static function to be used in two .c source files?

I don't want to put the static function definition in two source files(of the same module),
as that's duplicate.
Also I have to declare it as static, because I don't want other modules to use it.
What should I do?
Put the function header in a header file (.h).. can I suggest you find a good C tutorial ?
This sounds like mutually exclusive requirements; you want a single implementation of a function to be shared between two translation units, but you want to declare it static so that it isn't visible to other translation units. Unfortunately, C doesn't offer that kind of granularity; a symbol is either visible to all other translation units or it isn't.
You can fake it by putting the function definition in a header file (declared static), and then #include it in the source files that need it:
#ifndef FUNC_H
#define FUNC_H
static void func() {...}
#endif
The thing is, each translation unit that includes this file will have a redundant implementation of the function. That may or may not be a big deal for you.
Personally, I'd just declare the function normally in its own translation unit, create a header for it, only include the header in the files that need to call that function, and document that function should only be called from those files.
Not sure what do you mean by two files of the same module, but the point of static function is that their scope is limited to file, so the best you can do is to #include one file into the other instead of linking them together. If I got your right...
If the function is short or simple, you might define it (giving also its body) in a header file as a static inline function, e.g.
/* in header.h */
static inline int sum3(int a, int b, int c) { return a+b+c; }
But you really should read a good book on programming in C.
The primary purpose of the static keyword is to create an object that will exist throughout the duration of the program. But all objects declared at file scope ("global") behave in this way, no matter if they are static or not: they have static storage duration.
But it also means that the object cannot be accessed outside the scope it is declared. Functions are declared at file scope ("global") and therefore a static function will only be accessible from the very same file it is declared in. So it doesn't make sense to declare such a function inside a header.
What I think you are trying to do is this:
// function.h
void the_func (void);
// function.c
#include "function.h"
static void the_private_func (void);
void the_func (void)
{
do_things();
do_private_things();
}
static void the_private_func (void)
{
...
};
// some_caller.c
#include "function.h"
...
the_func();
At least this it what makes sense in an object-oriented design.

Does it prohibited calling classic C function from Objective-C++ class method body?

I have experienced some strange behavior of Objective-C++.
I have an Objective-C++ class, and it calls a classic C function in a method body.
But linker cannot find the C function.
I described the problem here:
Xcode print symbol not found for my C function which used in Objective-C method body
I solved the problem by changing Objective-C++ class to Objective-C class, but the question is still remained. Does it prohibited calling C function in Objective-C++ class?
You need to make sure that the C functions are declared
extern "C"
in the appropriate .h file.
The common way of doing this is:
//
// foo.h
//
#ifndef __FOO_H__
#define __FOO_H__
#ifdef __cplusplus
extern "C" {
#endif
// ... your interface here - normal C function declarations etc ...
#ifdef __cplusplus
}
#endif
#endif

Resources