Using Lib file alonside DLL (as apposed to function pointers) - c++

I've always found it a bit of a pain that you have to use LoadLibrary() and define function pointers when wanting to make use of a DLL, it just feels a bit archaic when so much is automated now days. So when I stumbled across a forum post explaining that the VS auto-generated lib file that always (in my experience) gets compiled alonside your DLL can be used to save yourself the hassle, as a sort of auto-import mechanism, I figured I'd put it to the test.
I created two very minimal projects to test this, but it doesn't appear to be working.
The code in its entrirety for the DLL:
extern "C"
{
__declspec(dllexport) int get10()
{
return 10;
}
}
And for the exe (an otherwise empty Win32 console app):
#include <Windows.h>
#pragma comment(lib, "Kernel32.lib")
#pragma comment(lib, "dll1.lib")
__declspec(dllimport) int get10();
int main(int, char**)
{
int x = 0;
if (LoadLibrary(L"dll1.dll") != NULL)
{
x = get10();
}
return 0;
}
dll1.dll and dll1.lib are local and visible to the project, but when I go to link it get10() is unresolved. If I remove the call to this it builds and runs and the LoadLibrary() call succeeds.
I also tried copying across the dll1.exp, just clutching at straws really, but that didn't help either.
Is what I'm trying to do actually valid?
By the way I appreciate you'd usually just use a lib file proper, it just grabbed my curiosity for circumstances where you might have these dll and "reduced" lib files but not have the source to compile a regular lib file.

You either link as static, or as dynamic.
So, in essence, you need __declspec(dllexport) only if you're loading the function at runtime by name. Read some of this, for example.
As mentioned here, regarding __declspec(dllexport):
This convenience is most apparent when trying to export decorated C++ function names. Because there is no standard specification for name decoration, the name of an exported function might change between compiler versions. If you use __declspec(dllexport), recompiling the DLL and dependent .exe files is necessary only to account for any naming convention changes.

Related

How to use a provided DLL file with HPP header?

I’m currently having some problems trying to implement an integration with a Verifone PoS.
The bank we are working with provided us with one .dll file, one .h file and one .hpp file.
I’m usually a Java or PHP developer, so for the last days I consumed everything I found on the web about DLL files and how to use them, but none seemed to work so far. I got a lot of errors, many of them being something like “invalid dll”.
I found on the web that alongside a dll file there should have been a .lib file. I asked the third party about this, but apparently
There is no .lib file. The .dll file contains all the required info for an integration
From their documentation of library I found this:
The form of the supplied binary is a dynamic library. By its nature, a dynamic library allows for easier updates and corrections, not requiring recompilation or relinking of the client (calling) code, as long as the procedures prototypes (function parameters and return types) remain the same.
The language used for the library implementation is C++.
To access the functionalities implemented in the library binary, a C-style header interface is provided. This is comprised of the function prototypes available to be called as well as the types of the result-structures through which the returned data needs to be interpreted to make sense for the previously accessed functionality (the specific requested transaction).
So yeah, the .h file includes only the data types, and the .hpp file contains some declarations that looks like this:
extern "C" __declspec(dllexport) bool doSomething(int param);
Also in their documentation there is an example of how an implemetation should look (and it is fairly simple):
bool someVar = doSomething(1);
It looks like those functions can be called as simple as that, but they cannot. If I try to do that I get an “undefined function” (or similar) error.
At this point the only thing that seemed to have somehow worked (maybe) is loading the DLL with the LoadLibrary function. But besides the fact that whatever function I try to call, with whatever parameters, it returns false, it seems kind of wrong that I do not use the .hpp file at all.
So here we are. How I should aproach this? Is there a way to load the DLL and use the provided HPP file as function definitions? If not, is there another way beside LoadLibrary + GetProcAddress combo to do this?
Thank you!
I'm assuming the dll is a native dll, not a managed assembly (.net dll).
Usually, the dll author adds a preprocessor definition to the build system, like DLL_EXPORT. So if the author compiles the dll, the import library (a small .lib file) will contain all functions that used the DLL_API macro. Then the author can ship the very same header to a user. Because that user won't have the DLL_EXPORT macro defined, DLL_API will resolve to a dllimport, which basically says that the annotated function is defined in the import library.
Such a header might look like this (the whole #if condition is usually in its own header file which is then included in all headers that export functions):
#ifdef DLL_EXPORT
# define DLL_API __declspec(dllexport)
#else
# define DLL_API __declspec(dllimport)
#endif
extern "C"
{
void DLL_API SomeFunction(int x);
void DLL_API AnotherFunction(int x);
}
If the author builds the project (in msvc) the compiler will generate the dll file and a small .lib file, which is the import library. This lib will essentially do what you have to do now: calling LoadLibrary and GetProcAddress to resolve all the functions that have been annotated with __declspec(dllexport).
The following part is a bit speculative and I'm guessing a bit here.
All __declspec(dllimport) does, is tell consumers that this dll contains those functions. But the linker has to link a declaration to its definition (implementation) so the function must be defined somewhere at compiletime. And that place is the import library (.lib). If you don't link with the import library, you will get a linker error when you build your project.
This means simply changing the dllexport to a dllimport won't solve your problems. Without an import library your only option is to load the dll manually with LoadLibrary and search for each function.
If I were you, I'd ask the author for an example project that uses the dll. AFAIK, the only ways to use a native dll is either by linking to an import library or by loading everything manually.
Manually generating the import library from the dll
I've tested this to make sure it works.
First of all, fix the header file to either use the macros like I did in the example above, or just use dllimport directly.
Second, open the developer command prompt for VS and follow the steps from this answer. Make sure to use the correct file names and target architecture (x64 or x86). Now you should have a .lib file.
Thrid, add the lib to your project.
Add the directory of the lib (place it somewhere close to the project so you can use relative paths). Open the project properties and follow the steps in this image:
Make sure that Configuration and Platform are correct (you probably want it like in the image). You can also use relative paths. Click on the Macros button to see all predefined paths available to you.
Add the lib to the linker dependencies:
Put the header somewhere in your project where you can access it.
Now you can simply include the header anywhere in your project and use the functions declared inside it. But note that the dll file has to be placed somewhere where LoadLibrary can find it. Preferably this is the same directory where your project's executable is located.
Bonus facts
The definition file (.def) is actually very simple. The def file for my sample code above is:
LIBRARY MyLibrary
EXPORTS
AnotherFunction
SomeFunction
If I remove the extern "C" block around my declarations, my function names will be mangled and the def file looks like this:
LIBRARY MyLibrary
EXPORTS
?AnotherFunction##YAXH#Z
?SomeFunction##YAXH#Z
If you put those functions inside a namespace (for example FooSpace), that namespace name will also be part of the function name:
LIBRARY MyLibrary
EXPORTS
?AnotherFunction#FooSpace##YAXH#Z
?SomeFunction#FooSpace##YAXH#Z
Note that all extern "C" entities will ignore namespaces, meaning all extern "C" functions, variables, types, ... will be put into the global namespace, no matter if you define them inside a namespace or not.
These are also the names that you'd have to pass to GetProcAddress if you did it manually.

Visual Studio Force Library Import C++

I have two Visual Studio C++ projects, that generate the following outputs:
L.lib
E.exe
I would like to add a dependency between E.exe and L.lib, without actually calling any methods exported from L.lib. L.lib exports a single function:
__declspec(dllexport) unsigned foo();
Then in E.exe, I have the following compilation unit:
// L.cpp
#pragma comment(lib, "L.lib")
extern unsigned foo();
The issue is that since foo is unused by E.exe, the dependency on L.lib is optimized away. What is the best way to force the dependency on L.lib, without actually executing any code? The best that I could come up with is the following (appended to L.cpp from above):
__declspec(dllexport) decltype(&foo) bar{ foo };
However, the above results in generating additional files (E.lib, among others) during the linking process, and adds public methods to the EXPORTS table of the resulting E.exe executable. Can anyone think of a better way to force an entry into the EXPORTS table?
I know that I could disable the linker optimization to remove unused code, but that would affect the entirety of E.exe, which I don't want to do.
MORE INFORMATION
The issue that I am seeing is that E.exe has a transitive dependency on a third-party L.lib (and associated L.dll) which is non-relocatable (e.g., linked with the /FIXED option). By the time L.dll is loaded, the fixed memory address it is required to be loaded at has been taken by other DLL's loaded by E.exe. I need a way to ensure that L.dll is loaded as early as possible, to prevent another DLL from taking the memory addresses that L.dll requires in order to function properly.
Just take the address of foo in a way that can't be optimized out: auto volatile pFoo = &foo;. It's not actually called, but the compiler can't prove it's not called so it has to play it safe.
[edit]
Visual Studio is apparently more aggressive than I thought, with LTCG. Adding pFoo=pFoo; fixes it. Linker map: 0003:0000037c ?pFoo##3R6AXXZA 0040337c
While MSalters answer works in 90% of cases, it failed to always add a reference to L.lib from E.exe. In addition, his edited suggestion requires modifying the body of a function that is used by the executable. I was looking for a solution that only required including an additional source file (compilation unit) sent to the linker.
After further investigation, I determined that the following code does exactly that:
// L.cpp
#pragma comment(lib, "L.lib")
extern "C" unsigned foo();
#pragma comment(linker, "/include:_foo")
This forces you to know the mangled name of foo, but it my case that was easy to determine due to the extern "C" declaration.

C++ - Resolve linker error when working with static and dynamic libraries

I'm looking to make a set of libraries that a developer can use, and they can decide if they want to use them as dynamic libraries, or static libraries. Of course, this brings up several issues of complexity, the current of which is symbol resolution. In my test code, I have 3 projects: The executable project, the static project, and the dynamic project. As the name implies, the static project is compiled to a .lib, and the dynamic project is compiled to a .dll.
The static project includes the header for the dynamic project's code, and calls the function DynamicFunction, which means it will try to link to this function at compile time. However, the dynamic project being compiled to a shared library, it's not available, and it doesn't link. Is there a way for me to define the function, in any of the three projects, to resolve this issue?
My test code is as follows:
main.cpp - compiles to the executable
#include <Windows.h>
#include "../static/static.h"
using proc = void(*)();
proc p = 0;
// I tried using this to force there to be a DynamicFunction function to link with,
// But since they're in different compilation units, it doesn't quite work.
void DynamicFunction() {
if (p) {
p();
}
}
int main(int argc, char** argv) {
HMODULE dll = LoadLibrary("dynamic");
proc p = (proc)GetProcAddress(dll, "DynamicFunction");
UseDynamic();
}
Static.h
#pragma once
void UseDynamic();
Static.cpp
#include "../dynamic/dynamic.h"
#include "static.h"
void UseDynamic() {
DynamicFunction();
}
dynamic.h
#pragma once
extern "C" __declspec(dllexport) void DynamicFunction();
dynamic.cpp
#include "dynamic.h"
void DynamicFunction() {}
I recognize the error is stemming from UseDynamic's assumption that the function is also defined statically, but I'm not aware of any way to have it be aware of whether or not the function is static or dynamic without having knowledge of how another library is being used, and even it would probably involve some ugly preprocessor conditionals.
Is is possible to do what I'm looking to do, or would I need to decide on either static or dynamic libraries (or at the least, not allow mixing the two)
Edit: I'm working with Visual Studio 2017
When you build a DLL project in Visual Studio, it will build a static import library along with the DLL. This library contains shim definitions of the functions your DLL exports that will take care of loading them from the DLL. Linking your test executable to your DLL's import library should get things working.

How do I get started writing DLLs in visual C++?

As the title says, although I guess what I really mean is "And using them later."
The Setup
I have followed this answer:
https://stackoverflow.com/a/13219631/696407
which creates a very simple dll
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromMyDLL()
{
printf ("Hello DLL.\n");
}
}
and I now have a dll compiled for release:
DllTest.dll
DllTest.exp
DllTest.lib
DllTest.pdb
When I run DllTest.dll through dumpbin, I find this line:
1 0 00001000 DisplayHelloFromMyDLL = _DisplayHelloFromMyDLL
USING THE DLL
To use that function in a new solution, I believe I must
Start a project in a new solution
Add the location of the DLL to the project under
Properties
Configuration Properties
Linker
General
Additional Library Directories
Add the .lib file under
Properties
Configuration Properties
Linker
Input
Additional Dependencies
and, having added the .lib there, the next step is... hvæt?
My code right now:
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
while(1)
{
DisplayHelloFromMyDLL();
}
return 0;
}
but that doesn't work.
EDIT: I guess "doesn't work" is vague. The function gets Error: identifier "DisplayHelloFromMyDLL" is undefined
(Side question: Is my function called DisplayHelloFromMyDLL(); or _DisplayHelloFromMyDLL();?)
You need .h for compiler (use with #include, and add the folder to .h file as relative path to Configuration Properties > C/C++ > General > Additional Include Directories). Aside from .lib for linker you also need .dll to actually run the test application.
EDIT: There are two types of DLL's that you can make. First are C-like DLL's, with functions that have signatures as if they are written in C instead of in C++. All Windows DLL's (user32.dll, shell32.dll, version.dll) are built as such. The other are C++ DLL's, with functions that are part of the class. MFC and Standard C++ Libraries are such.
If you want to make a C++ DLL then you have to declare all classes that are part of interface as __declspec(dllexport) in your DLL project and __declspec(dllimport) in all projects that would use DLL. Usually the same file is used for this, but with a macro that is defined accordingly to one or the other. If you create a DLL from Visual Studio project template you would see this code.
Your case is actually the simpler case, as you want C-like DLL. You don't have to fiddle with this __declspec rubbish, but you need one additional .def file in DLL project. This should be the content of the .def file:
LIBRARY MyApi
EXPORTS
DisplayHelloFromMyDLL
Your header file (.h file) should look like this:
#pragma once
#ifndef HELLO_DLL_INCLUDED
#define HELLO_DLL_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
void DisplayHelloFromMyDLL();
#ifdef __cplusplus
};
#endif
#endif // HELLO_DLL_INCLUDED
__declspec(dllimport) tells the compiler that this function (or class) is defined somewhere else, and that linker will find it and link it. __declspec(dllexport) tells the compiler (and linker) that this function (or class) should be exported and be part of DLL interface. If class has neither of those then it's just a class that should be defined in the same project.
To consume your .dll you need two things, a header file and a .lib.
The header file is so that the compiler knows there is a function somewhere with the name DisplayHelloFromMyDLL(). At this point it doesn't matter where it is, just that you've told the compiler it's somewhere. The linker will take care of the where bit.
The .lib file is for the linker. It tells the linker that DisplayHelloFromMyDLL() lives in a .dll, and that (in your case) the name of the dll is DllTest.dll. When your program starts up the Windows loader will use this information to load the .dll into your process and will perform any address fixups to make sure that calling DisplayHelloFromMyDLL() in your application calls the function in your .dll.
You don't actually need the .dll in order to build your executable, only to run it.

How do I fix an Unresolved External Symbol error in my C++ DLL?

I have a dll, which accesses some classes outside of its project (I'm using Visual Studio, so I have two projects). The thing is, in the header that the dll includes, which is outside of the dll's project, there are only bodies of functions, like this:
x.h
class x
{
void myFunc();
}
And in another cpp file, outside of the dll file:
#include "x.h"
x::myFunc()
{
//.....
}
The dll is only getting the bodies of the functions, so when I compile, I get lots of unresolved external symbols (I'm quite sure that this is the issue, because I tested with another class fully built in a .h file, in another project, and no errors). So how can I solve this mystery?
It is normal for the import headers to only have function signatures; the actual function bodies are already compiled into the DLL binary and are resolved at link time by linking into the actual DLL.
The first thing to try is to make sure you are actually linking to the said DLL. It isn't enough to just include the header, you also need to link to the binary. So in your project configuration, you need to add a link to (for example) the .lib file that gets created along-side the DLL when the DLL is compiled (if in MSVC). This lib file lets the linker know how to connect the function signatures you included via the import header to the actual implementations contained in the DLL. If you're on a different platform, the mechanics might be a little different, but the concepts will be similar.
Edits:
The next step is to make sure the binary is actually exporting the symbols you're trying to link against. Make sure that all interface signatures are being exported via __declspec(dll_export) prefixes. Normally this is wrapped up in an IFDEF so that the header is declared export while the DLL is being compiled, but not when that header is included in a client project. Next, you could use dumpbin to check the mangled export names, and see if there is anything unexpected.
Here's a modified version of your example that illustrates this style of export (note, I haven't tested if this compiles, apologies for any typos):
#ifdef BUILDING_MYDLL
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
class MYDLL_API x
{
void myFunc();
}
You would then set your configuration to define BUILDING_MYDLL when compiling the dll, but not when compiling the executable. This way the functions are only marked export when compiling the library dll. Now you can mark your public API functions with MYDLL_API and they should get exported during build.
Please note that dll_export, dll_import, and declspec are all very MSVC-specific constructs. Other compilers/runtimes handle symbol export in different ways.
There's multiple ways to link DLL into your app on Windows, check out this existing question/answer:
https://stackoverflow.com/a/2060508/1701823