I wanted to create a C++ dll (to be used in a dot net application). Some functionality I needed was already implemented in another C++ dll.
The dll I was referencing was set up like this (including the comment):
extern "C"
{
__declspec(dllexport) BOOL SomeFunctionToBeUsedExternally();
}
// internal functions
BOOL OtherFunctions();
I need to use one of the OtherFunctions in my code.
So, I added the proper include in my own code, added dependencies on the lib created by the dll above, and used the method I needed. As a result, of course, I got another __declspec(dllexport)... function.
It refused to link though, I got an error about the OtherFunction.
I verified everything, looked online - nothing seems to solve my problem.
Then, I added a __declspec(dllexport) in front of the function I needed, and it works.
I don't understand though. I thought, the dllexport marked functions will be exported to the dll, but aren't all functions sent to the lib ?
Why do I have to export functions to the dll, if I am not linking against the dll but against the lib ?
No, the linker does not automatically export all identifiers. The dllexport attribute tells the linker which identifiers are exported. Without this you would be forced to either export every identifier in the DLL or specify which identifiers should not be exported. When the linker creates the DLL it also creates an import library and includes information about which identifiers are exported based on that attribute.
When you want to use a DLL you need link with the appropriate .lib file for good reason. The .lib file tells the linker which identifiers are exported, the name of the DLL they are in and other information. It is also possible to export identifiers from the DLL by ordinal instead of by name. In this case the linker still needs to match the identifier with the appropriate ordinal. This is only possible by having an accompanying library file that contains that information since it is not present in DLL's export table.
No, only exported functions end up in the .lib. As you can tell.
It is not a static link library, it the import library for the DLL. It is a very simple and very small file since it contains no code at all. Just a list of the exported functions. The linker needs it to resolve the external in the client code, it needs to know the name of the DLL and the actual exported function name or ordinal (could be different) so it can add the entry to client's import table. Import libraries having the same filename extension as static libraries was perhaps a bit unfortunate.
Related
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.
In a Windows environment,
When I tried to link a DLL to my program Explicitly (using LoadLibrary),
First I need to define the function pointers according to each
function signature inside the DLL.
Then get the function addresses using 'GetProcAddress' and assign them to those pointers.
When I tried to link the DLL to my program Implicitly (using header file)
First it need the relevant header file to get function signatures.
Then it needs the relevant Lib file that was generated with the DLL.
My questions are
Why does implicitly linking need a Lib file as well?
What information does it need to retrieve from 'Lib' file that it cannot get from the DLL or Header file?
If there is something for question 2, how is information retrieved when explicitly loading?
I've already gone trough this question. But I cannnot understand any worthy reason.
Please, could someone help to explain this in simple terms. Thank you.
Why Implicitly linking need Lib file too.
The .libs have the import information of the dll, you can check the information using the dumpbin command that is included in Windows/Visual Studio SDK.
This is the link information of recv inside ws2_32.lib for example:
Version : 0
Machine : 14C (x86)
TimeDateStamp: 4907F6ED Wed Oct 29 01:38:53 2008
SizeOfData : 00000014
DLL name : WS2_32.dll
Symbol name : _recv#16
Type : code
Name type : ordinal
Ordinal : 16
You can check there is the ordinal and the name inside ws2_32.dll (check that now it says to import a DLL).
What information it need to retrieve from 'Lib' file that cannot get from DLL or Header file
In the header file, there is no information from where to extract the imports, so them are marked as imports (__imp__name) when compiled, and when it's linked against the .lib, it resolves the name:
If it's inside the .lib it just links against it.
But if there is information on external reference (DLL), it will construct the import inside the import table so it's loaded dinamically.
If there is something for question 2, How those information retrieve when explicit loading.
If for explicit loading you mean the LoadLibrary, you are telling it at runtime and not at link time. So the PE loader will search the DLL inside the PATH and will load it dynamically. Then you have other functions to get the exported functions addresses.
If you don't understand something just ask me, try playing with dumpbin and read about PE if you want to understand this better.
When linking implicitly, the function declaration specifies the name to be used in the program, and the prototype and calling convention. But more information is needed. Specifically:
The fact that the function is implemented externally in a DLL.
The name of that DLL.
The exported name of the function. That is the name used to export the function from the DLL which may not be the same as that used when you import it.
Some language designers chose to provide this information using language extensions. For example Delphi took this route. Implicit linking is specified entirely in code with no .lib files. On the other hand the convention for C and C++ is to use .lib files to specify the missing information.
I have a native C++ class that is exported to a Win32 Dll:
class __declspec(dllexport) Manager { ... }
The Dll is created successfully. Let's call it Unmanaged.dll.
I want to use this class in a .Net application. Therefore, I decided to create managed C++ wrapper classes. So I created a new CLR class library where I set Unmanaged.dll as an input to the linker.
When compiling the managed dll I get the following error:
fatal error LNK1107: Invalid or corrupt file: cannot read at 0x318. (Unmanaged.dll in project ManagedBridge)
Both projects are set to compile to x64. DLL Export Viewer shows the class' constructor and methods. So the Dll seems to be fine.
Is there something I am missing?
You cannot pass a DLL to the linker, it has no idea what to do with it. A DLL is in general not suitable to help a linker determine that the DLL contains the functions you call. Exports from a DLL can be a number of a name. It being a number (an "ordinal") is a problem, the linker will not know how to map the number to the identifier name. And the name does not have to match either, names are commonly simplified with their name decoration removed.
You must instead tell the linker about the DLL's import library. Which has more information, including the ordinal to name mapping and the original decorated name that the compiler used. The import library is a .lib that was created when you linked the DLL. You will find it back in the DLL project's build directory. Add its path to the linker's Additional Dependencies setting.
How do you merge multiple static linked libraries into a single dll given each static lib defines exported functionality (vc++ 2008)?.
In a multi project layout existing out of a single dll project and multiple sub projects that are linked in statically (in the dll project). Despite being marked as __declspec(export) some of the symbols in the sub-projects (.lib) refuse to have their symbols exported in the final dll.
Generating a .def file and marking the symbols explicitly for exportation could solve this problem. However identifying which of the symbols are marked as __declspec( export ) proofs a problem. Due large number of exported classes/function and primarily name mangling maintaining a list by hand is a unfordable process thus generating the list of symbols, that were marked for export, would be the only viable option.
Is there an utility or compiler directive could do this?
Use a DEF file.
Always use a DEF file.
Never fail to use a DEF file.
Just accept that a DEF file is the thing to use.
Stop using __declspec(dllexport), and use a dang-dratted def file already.
Also don't export classes. Export those class members which need to be exported only. And use a DEF file to do it.
Seriously, if you export classes without a DEF file, the function names will be several times longer than the actual program data. You should to use ordinals for exporting C++ member functions.
After bit trial and error I found that using the lib /def command can be utilized to generate an import library and export file. It appears that the export file contains all symbols that are marked with __declspec(dllexport). Subsequently the .exp file can be inspected with dumpbin and used as a reference to generate a module definition file.
Starting with Visual Studio 2015 Update 2 there is a new way of doing this, by using the linker option /WHOLEARCHIVE
It's documented here
The /WHOLEARCHIVE option forces the linker to include every object
file from either a specified static library, or if no library is
specified, from all static libraries specified to the LINK command. To
specify the /WHOLEARCHIVE option for multiple libraries, you can use
more than one /WHOLEARCHIVE switch on the linker command line. By
default, the linker includes object files in the linked output only if
they export symbols referenced by other object files in the
executable. The /WHOLEARCHIVE option makes the linker treat all object
files archived in a static library as if they were specified
individually on the linker command line.
I am interested in using my static lib to create a dll (implicitly linking). which means I need to (in vs2008)
create a dll project that should generate the following:
header file (which have export function declarations. These are simple wrappers to actual functions in the static lib using __declspec(dllexport) which are in the .cpp )
import lib which will be made as a result of creating the dll
the actual dll which is created.
I have made a test program that will utilize the above dll(including the import lib/header files) to test it.
in this I have included all the three items. now the exe compiles/links without issue.
however in the main.cpp when i call the exported functions (with the associated __declspec(dllimport) call it never seems to execute. I am uncertain why this is?
Its almost like the even though the exe can see the exported function in in the dll...the dll cannot call on the code that is in the static lib?
i just cannot answer why my exe can't see the code in the static lib? do i need an archiver/librarian for vs2008 to include all those obj files as part of the import lib?
I am at a loss and am not sure how to test this?
other than just making my static lib directly into a dll. I wanted to try this method. I know i am missing something...i have read all over the place and i am just stuck. There were some threads here that had some people posting something similar but i can't seem to get it. please be as detailed as possible as I am new to this. thanks again.
update 1:
ok so currently i added the extern line to the function prototype and now it sees the exported function from the dll. however, now the only issue left is that:
i can't invoke the function that this exported function (aka wrapper) is trying to call. which happens to be in the static library. how should my exe get visibility to that static library function. I know it can be done because I think there was one other person on this board who was able to make this work.
update 2: my setup is exactly like this questioner...
How to force inclusion of an object file in a static library when linking into executable?
but i am not using explicit linking. i am using implicit linking. my real issue is how to call a static lib function in my dll wrapper which is exported to the exe?
If the app and DLLs are MFC app/dlls, then make sure that the application and all dlls are either "Debug" versions or "release" versions and not a mix.