Creating a DLL, confusion with __declspec(dllexport) - visual-studio

Visual Studio C++ 2005
Windows XP
I am creating this DLL library. The DLL actually links with another LIB. I have included the headers and lib path. Everything compiles ok.
Actually, this code I wrote for running on linux, which runs ok. Now I am porting it to run on windows.
However, I have noticed that some DLL from some code samples use this in there header file:
static __declspec(dllexport) float some_function(int num1, int num2);
However, I have done the following, sample code below for the header *.h file. However, not sure if I still need the above or not?
#ifdef __cplusplus
extern "C" {
#endif
media_t* get_media(media_description_t* obj);
void* get_item(media_description_list_t *obj, int num);
int get_number_format(media_t *obj);
const char* get_media_value(media_t *obj);
#ifdef __cplusplus
}
#endif
Sample code for for implementation *.cpp file
int get_number_format(media_t *obj)
{
Media *med = (Media*)obj;
return med->getNumFormat();
}
So, do I need this static __declspec(dllexport)?
Many thanks for any advice,

The linker needs to be told which of your functions should be exported, making them usable by other code that uses your DLL. __declspec(dllexport) does this. But you can also do it by providing the linker with a .def file, a list of exported function names. Somewhat painful because it now is up to you to keep that file in sync with your code. Docs are here.

__declspec(dllexport) adds the function to the DLL's export table. This table is a convention that allows a process wishing to use the DLL to correctly call the function.
There are other ways to export functions from DLLs, but this one is probably the more modern and easier to use.

yes it is needed, if you don't have the dllexport the function will not be accessible in any other application where you are calling that function.

If you put the implementation of a method in the h file, you don't need to use the __declspec(dllexport) declaration.

Related

Replacing MSVC CRT function with private implementation

I have an embedded IoT project that I like to first develop in part by using PC tools such as VisualStudio. My embedded project has only a flash memory for a file system, and I'd like to redirect fopen fread etc. to my own private implementation on Windows. But what I'm encountering is an inability to have my private CRT library take precedence over the built-in CRT (e.g., built-in behavior driven by /MD compiler switch).
I have a simple three project solution.
Project 1 is a test executable. It has a one line main:
int main()
{
test();
}
Project 2 and 3 are static libraries. Project 2 has:
#include <string.h>
#include <stdio.h>
void test()
{
printf("%s\n", strchr("x", 'x'));
}
Project 3 has:
char * strchr(const char * s, int c) // exact signature of MSVC
{
return "overridden";
}
I expect output to be overridden but instead it is
x
But if I add this to Project 1:
printf("%s\n", strchr("y", 'y'));
The output will be
overridden
overridden
First one from test() in library, second from executable main() directly.
Any suggestions?
The linker resolves symbols on a first match basis - priority to separately linked .obj files, then .lib files in the order presented to the linker of the command line. So you can normally override a library symbol just be linking your own replacement. I have never tried it with MSVC, and it is a somewhat brutal approach.
An alternative solution that does not rely on specific linker behaviour is to use the pre-processor to replace standard symbols with your own alternatives. For example:
#if defined _WIN32
#define fopen test_fopen
FILE* test_fopen( const char * filename, const char * mode ) ;
#endif
add the other macros and declarations you need in a header file called testlib.h for example then use a "forced include" (/FI testlib.h in MSVC) to invisibly include the test interface everywhere. Then when built on Windows, all fopen calls will be replaced with test_fopen calling your replacement functions instead.
If the problem is caused by CRT usage in a static library only, and linker is finding MSVCRT DLL export lib before it finds private CRT static lib, a workaround might be to force a reference to the private CRT in the executable source files.
Example matching code above, placed in main as a global:
static char * (*p_strchr)(const char *, int) = strchr;
It is less than ideal but it alters linker search order in a reliable way.
More findings
There may be combinations (that I don't totally understand) where the linker will emit a LNK1169 "one or more multiply defined symbols" (more than one definition) linker error. For example, it might say fopen is defined more than once, and if you reverse the order of the private and MS libraries on the command line, then it might say fread is defined more than once. Perhaps it is caused by MSVC lib having DLL export signature, and the private lib being an import symbol. The behavior is hard to determine as it doesn't error on all of the functions that are being overridden.
If it is possible to switch all private libraries to /MT compiler switch (use static CRT), then the LNK1169 problem is resolved.

Error when including winuser.h. It defines ChangeMenu to ChangeMenuW or ChangeMenuA

Working on a Qt app on Windows. I include QVboxLayout in my source file only and this causes errors because its macro overwrites my method name.
foo.hpp
class foo
{
ChangeMenu();
}
foo.cpp
#include "foo.hpp"
#include "QVBoxLayout" // <--- this includes winuser.h
foo::ChangeMenu(){};
Now what happens is winuser.h has a macro
#ifdef UNICODE
#define ChangeMenu ChangeMenuW
#else
#define ChangeMenu ChangeMenuA
#endif // !UNICODE
This changes my function definition to ChangeMenuW but my declaration is still ChangeMenu.
How should I solve this? How can winuser.h define such a "normal" name as a macro?
Version of winuser.h is "windows kits\10\include\10.0.16299.0"
Pretty much any Windows API that deals with strings is actually a macro that resolves to a A or W version. There's no way around, you can either:
avoid including windows.h, but as you noticed, it creeps through;
brutally #undef the macro before defining/using your function; this is a fit punishment for hoarding such normal and non-macro-looking identifiers, but is tedious and some other code may actually need the Win32 function;
just accept it as a sad fact of life and avoid all the relevant Win32 APIs names; if you use Qt and follow its naming convention, it should be easy, as Qt functions use lowerCamelCase (as opposed to Win32 UpperCamelCase);
include windows.h explicitly straight in your header (possibly under an #ifdef _WIN32); this will make sure that your identifier will get replaced by the macro in all instances, so everything will work fine even if the compiler will actually compile a function with a different name; suitable for standalone projects, not suitable for libraries. (Thanks #Jonathan Potter for suggesting this)
You could take no care about this issue, Although your method name will be the same as the windows API, but the system will not mix them(just unify Unicode on both the place to define/call). If you call the ChangeMenu() directly, you will call the winapi, and if
foo f;
f.ChangeMenu();
or
foo::ChangeMenu();(static)
You will call your method.
And if you want to disable the winapi:
#ifdef ChangeMenu
#undef ChangeMenu
//code place that you define/call your own ChangeMenu().
#ifdef UNICODE
#define ChangeMenu ChangeMenuW
#else
#define ChangeMenu ChangeMenuA
#endif // !UNICODE
#endif
(It looks very tedious.)

use a function from dll in visual studio 2010(visual c++)

I made a dll from my project and export a function using extern "C" like the code below:
main.cpp
extern "C" __declspec(dllexport) void __cdecl VectorOfMarker(char* InAdd,vector<NewMarker>& VectorMarkers)
{
DetectSeg d;
d.VectorOfMarker(InAdd,VectorMarkers);
}
I build the project and create the .dll and .lib files successfully.
then I create a new visual c++ project and try to use this dll and mentioned function in it.
Although I copied the .dll and .lib files to the same directory but I can't use extern "C" to import my function to the 2nd project. I think that I need to change some settings in visual studio 2010 to use the functions
Can anyone help me for this?
How can I use my exported function?
Too many thanks in advance
I think you are confused as to what type of the dll you are building.
There are two typed of the dynamitic linking implicit and explicit
.
To dynamically link a dll implicitly, you create dll that exports some functions and/or variables. This will create a DLL module and .lib import library. The module that is using this type of the dll, must have header file with function prototypes and must be linked with .lib import library.
So you are linking at the compile time. Since exports are done using __declspec(dllexport) and __declspec(dlleimport) and exported functions names are decorated (mangled). They look like ?ExportedTest##YAXPAD#Z.
Another type is explicit linking and that is most likely what you are doing.
Usually for this type of DLL function are exported using .def files to produce function names that are not decorated. This also can be achieved by using extern "C" modifier to tell C++ compiler to compile function as C style, hence exported function is not decorated and usre _ (underscore).
To use this type of the DLL you have todeclare function type and parameters, call Load library, and GetProcAddress to get function pointer. Then you will be able to make a call as follows:
typedef void (*DLLVectorOfMarker)(char*, vector<int>&);
HMODULE hMod = LoadLibrary(_T("ExportTest.dll")); // your lib name goes here
DLLVectorOfMarker pfnVectorOfMarker = (DLLVectorOfMarker)GetProcAddress(hMod, "VectorOfMarker");
vector <int> VectorMarkers;
pfnVectorOfMarker("some string", VectorMarkers);

VC++ / Dev-C++: How to include an DLL?

I have written an DLL in Delphi which exports functions. I would like to use these functions in a C++ program without using dynamic Linking (LoadLibrary() API-Call).
The "import" declaration would be
extern "C" int __stdcall getVersionNumber();
I mainly use Bloodshed Dev-C++ which creates Windows Executables. But I do not know how to tell the compiler that it should import the function "getVersionNumber" from "STATMONDLL32.dll".
After I spent many hours by googling the problem, without any result (there was only weird stuff written about .a files and .lib files, which I do not have compiled by Delphi...) I have also installed VC++, but even there, I could not find a way to tell the compiler to use a specific DLL.
I have created a DEF file for this DLL - how can I tell Dev-C++ and/or VC++ to use it? (Dev-C++ prefered)
// Edit: Delphi is creating UNDECORATED symbols. The symbol is exactly "getVersionNumber".
I have created following DEF file with an alias for decoration:
LIBRARY STATMONDLL32
EXPORTS
getVersionNumberA = _getVersionNumberA#0
I have created a *.lib file with VC++ "lib.exe":
lib.exe /DEF:StatMonDll32.def /OUT:StatMonDll32.lib
I have included the lib in VC++ linker settings.
But VC++ tells me that it cannot resolve the external symbol _getVersionNumberA#0 ! Please help!
// Edit: I have uploaded the DLL here: http://www.viathinksoft.de/temp/StatMonDll32.dll . Can you access the symbol getVersionNumberA with VC++ ? I am searching for a solution since 6 days now :'-(
Best regards
Daniel Marschall
You can use dynamic linking, it should work something along the lines of:
extern "C" typedef int (__stdcall *pfnadd)(int a, int b);
extern "C" typedef int (__stdcall *pfngetversion)(void);
HMODULE mod = LoadLibraryA("mydll.dll");
pfnadd add = (pfnadd)GetProcAddress(mod, "Add");
pfngetversion getVersionNumberA =
(pfngetversion)GetProcAddress(mod, "getVersionNumberA");
and then you can just call using the function pointer:
add(1, 2);
std::cout << getVersionNumberA();
Although, it seems like your question has bits and pieces of two different functions!

How do I control which symbols a Windows DLL imports from the application?

I'm trying to build a shared library (DLL) on Windows, using MSVC 6 (retro!) and I have a peculiar link issue I need to resolve. My shared library must access some global state, controlled by the loading application.
Broadly, what I have is this:
application.c:
static int g_private_value;
int use_private_value() {
/* do something with g_private_value */
}
int main (...) {
return shared_library_method ();
}
shared_library.c:
__declspec(dllexport) int __stdcall shared_library_method() {
use_private_value();
}
(Updated - I forgot the __declspec(dllexport) int __stdcall portion, but it's there in the real code)
How do I set up shared_library.dll so that it exports shared_library_method and imports use_private_value?
Please remember that A) I'm a unix programmer, generally, and B) that I'm doing this without Visual Studio; our automated build infrastructure drives MSVC with makefiles. If I'm omitting something that will make it easier to answer the question, please comment and I'll update it ASAP.
This is actually going to be pretty difficult to get working. On Unix/Linux you can have shared objects and applications import symbols from each other, but on Windows you can't have a DLL import symbols from the application that loads it: the Windows PE executable format just doesn't support that idiom.
I know that the Cygwin project have some sort of work-around to address this problem, but I don't believe that it's trivial. Unless you want to do lots of PE-related hacking you probably don't want to go there.
An easier solution might be to just have some sort of initializer method exported from the DLL:
typedef int (*func_ptr)();
void init_library(func_ptr func);
The application must call this at start-up, passing in the address of the function you want to share. Not exactly elegant, but it should work okay.
I'll start with half of the answer.
In shared_library.c:
__declspec(dllexport) int __stdcall shared_library_method(void)
{
}
The MSDN article about exporting function from DLL:s.
For the second half you need to export the functions from your application.c.
You can do this in the linker with:
/export:use_private_value#0
This should get you a lib-file that you build with your DLL.
The option to link the lib-file is to use GetProcAddress().
As DavidK noted if you only have a few functions it is probably easier to pass the function pointers in an init function. It is however possible to do what you are asking for.

Resources