.h, .dll and .lib confusion - visual-c++

I'm new to vc++. I've just built a software and it generated a .dll and a .lib. I need to use functions from this in my code. Do I need to link to both .lib and .dll to build my code? What project properties do I have to alter to do this linking?

Actually, you need only the .dll file. It contains all the necessary code and data to run it's functions. It also contains a table that links the symbolic names of the functions (e.g. the function PrintMe), their ordinals (the number of that function in the DLL) and their addresses in the DLL.
If you want to use only the DLL, you have to "manually" get the symbols resolved:
Let's say you want to use the function PrintMe of the DLL. What you had to do is to resolve it's name (PrintMe) or it's ordinal (PrintMe is the 1st function of the DLL) to it's address. For this, you could use LoadLibrary, GetModuleHandle and GetProcAdress from the Win32 API (aka Windows SDK). Additionally, this method allows you to load the DLL at runtime (see below).
The easier way is to use the MSVC(++) features __declspec(dllexport) and __declspec(dllimport), e.g.
// your DLL
__declspec(dllexport) void PrintMe()
{
printf("Hello World!");
}
// you project to use the DLL
__declspec(dllimport) void PrintMe();
The first one (dllexport) tells the compiler to export the function. The second one (dllimport) is the interesting one: It creates all the necessary code to be able to use the function from the DLL.
For this, you need the .lib file in your project (which wants to use the DLL). The .lib file contains information for the linker to resolve the symbol name (PrintMe) to its address in the DLL. Since the .lib is statically bound, the linker can make use of it - the DLL on the contrary is bound at runtime / loading time, so the linker cannot use it. (Yes, the information in the .lib file is redundant.). Note: You cannot change the whole DLL when using this method w/o rebuilding your project with the new .lib file. Some structure changes affect the addresses of the functions in the DLL, see this SO answer.
One last difference between using the Win32 API (LoadLibrary...) and the MSVC method via __declspec is the loading of the DLL. When you use LoadLibrary, the DLL is loaded at runtime, of course (so you can catch exceptions when it cannot be found and so on). The other method loads the DLL at loading time, so you program will terminate (will not run) when Windows cannot find the DLL.
When you create a project in VS, you can activate the "export symbols" checkbox at the end of a wizard (Win32 project). That gives you some examples of exported symbols. Additionally, it introduces a macro plus a preprocessor defition plus some directives that are very useful:
// DLL header
#ifdef _YOUR_DLL_EXPORTS
#define YOUR_DLL_API __declspec(dllexport)
#else
#define YOUR_DLL_API __declspec(dllimport)
#endif
YOUR_DLL_API PrintMe();
You now can use this header file to build you DLL as your DLL project has that _YOUR_DLL_EXPORTS definition (see project properties page, C++, preprocessor). The project that uses the DLL can use this header, too, but then must not have such a name defined. When you include the header file in the project in which you want to use the DLL, the macro is resolved to __declspec(dllimport). This instructs the linker to look for this function (which is found in the .lib file) and create all the necessary code to load the DLL at runtime and resolve the symbol name.

Related

how can I link a dll to fortran (visual studio)?

I have some DLLs that I want to use in a FORTRAN Project in VISUAL STUDIO but I can't find how.
Here is a simple code I'm using to find out how.
Using visual studio I created a DLL from this
subroutine printing
!DEC$ ATTRIBUTES DLLEXPORT::printing
print*,"dll naimi created"
end subroutine printing
I added the link of the DLL to project>properties>Linker>General>Additional Library directories
Main program:
program Console11
implicit none
call printing
end program Console11
ERROR : Error 1 error LNK2019: unresolved external symbol _PRINTING referenced in function _MAIN__.
other solutions related to this suggest using the .lib created while generating the DLL, but in my real case I only have the DLLs without their .lib.
So how to use a DLL ... ?
You appear to be trying to use a DLL as an input file to the linker.
(You also appear to be trying to specify a file for a linker option that takes a directory. To specify an additional input file for the linker, either add the file to the project just like you would attach a source file, or use the "Linker > Input > Additional dependencies" project property. The property you mention in your post then tells the linker where (which directories) to search for those additional dependencies.)
Unlike the unix convention, you do not link against DLLs when building executables and other DLLs on Windows. The DLL typically does not contain the necessary information for the linker - instead that information is contained in an import library (which is just a variation of a typical .lib static library) or equivalent.
If you were able to successfully build a DLL, then you will probably find the import library for that DLL in the same directory as the DLL. Supply that import library as an additional dependency for projects that require the DLL.
When you link an EXE or other DLL using an import library on Windows, the target DLL is automatically loaded by the operating system when your executable code is loaded. This is called load time dynamic linking.
If you do not have the import library for a DLL, then your choices are:
Ask the person who built the DLL for the import library.
Reference the DLL using run time dynamic linking, rather than load time. This means that you use the Windows API functions LoadLibrary, GetProcAddress and friends in your program to explicitly tell the operating system to load a particular DLL and to obtain the address of a function pointer. If you are using Intel Fortran, then complete examples of this are installed with the compiler - see in the file "C:\Program Files (x86)\IntelSWTools\samples_2016\en\compiler_f\psxe\DLL.zip" or similar.
Generate an import library from the minimum information in the DLL, plus other information about the DLL that you may have. One approach to this is to write a module definition file (.def) for the DLL, and then use the LIB utility to turn that def file into an import library. See How to make a .lib file when have a .dll file and a header file for an example.

What is the need for dllimport?

I am playing with DLLs to get a better understanding of them. So I created a simple dll (with load-time dynamic linking) which has functions to Add, Sub and Mul. In the header file for the dll I used __declspec(dllexport) for the function declaration.
For the executable, I added the .lib created after compiling the dll to the properties (for linking). After that I directly called the function Add without using __declspec(dllimport). The program worked. I then changed the function calling to __declspec(dllimport) (Add) and the program worked again.
I am not able to understand what the need of __declspec(dllimport) is? I have not yet coded a run-time linking DLL but from the examples I have seen, dllimport is not needed in that case as well.
Thanks for your assistance.

MSVC: __declspec(dllexport) does not symbols

I have a small issue when it comes to writing a DLL in MSVC (the 2010 version in particular).
My program consists of the main part and a DLL. The DLL contains a function that is
__declspec(dllexport) int test_function(void) {
return 42;
}
The file is compiled using a DLL project (not using pre-compiled headers, I have chosen a empty DLL project). Now, when I want to list the exported symbols using the dumpbin tool, the test_function is not listed under exports. Is there a specific setting that forces __declspec(dllexport) to actually export symbols?
Any help is welcome. Thank you!
That should do it. If this is the whole code, check the following:
1) You are actually checking the correct dll. Look at the timestamp. Double-check the location and the name.
2) You are compiling the specified cpp (I take it your definition is in the cpp file). Just because the file is in the directory doesn't mean it gets compiled, make sure it is added to the project.
3) Make sure your function is not excluded from the compilation unit by preprocessor directives.
Also look for other symbols and try to see what differences are there between the symbols that get exported and your function.
If this fails, you should move __declspec(dllexport) to your .h file and the definition (without __declspec(dllexport) ) to your .cpp. It might not be exported because the compiler might try to optimize it out by inlining it.

MSVC unresolved external symbol linking executables

I have two existing executables A and T, in the same solution that both ran just fine before I touched them. In executable A is a header defining a class P, and a prototype for a static instance MyP. The definitions are compiled in project A. In executable T, I wanted to call member functions of MyP in project A, so I added dllimport/export macros to the declarations of the class and MyP in the headers (not at the definitions), and included the headers in project T. The dllimport/export macros are standard, and A_EXPORTS is defined in project A, but not in T.
#ifdef A_EXPORTS
#define A_API __declspec(dllexport)
#else
#define A_API __declspec(dllimport)
#endif
//various definitions and includes, defining ENUM_RECORDING_TYPE and ERROR
A_API HFILE viosopen(const _TCHAR *path, ENUM_RECORDING_TYPE rt, int flags);
A_API struct P {
ERROR B(SHORT phraseNum);
};
A_API extern P MyP;
I added project A as a dependency on project T in the solution. A still compiles fine, but T comes up with unresolved external symbol "__declspec(import) <snip> referenced in function <snip> for the function calls, and unresolved external symbol "__declspec(dllimport) class P MyP" <snip> for the static object. I also see in the output log, right after it starts linking: Creating library Debug/A.lib and object Debug/A.exp which seems ominous since it's supposed to be linking against the existing executable.
My question is: how can I tell MSVC 2010 where those are? I thought simply setting A as a dependency would have it figure that out automatically. I can link against the existing executable, right?
To statically link your program you don't need the __declspec() stuff and you don't need a separate project to create a LIB file. I think you can just link using the .obj file from your A project.
Your A project has a header file and presumably has a .cpp file that contains the implementation of the items described in that header. Let's say your header file is foo.h and the associated implementation is foo.cpp. When compiled, there should be a foo.obj intermediate file in the <solutiondir>\A\Debug or <solutiondir>\A\release intermediate folder. That file can be used by the linker.
In project T's properties, find Linker | Input and change the "Additional Dependencies" property to include the foo.obj file. One approach would be to use a relative file path to locate the file - for example ..\A\Debug\foo.obj in your debug configuration. Another approach is to use the simple file name in "Additional Dependencies" - foo.obj - and then use Linker | General | Additional Library Directories" to help the linker find the file - e.g., ..\A\$(IntDir). Using the $(IntDir) macro has the advantage that the same value works for Debug and Release settings.
Remember to set up a build dependency from your T project to your A project to be sure the A project is compiled first. Otherwise the foo.obj file might not exist when the T linker comes to look for it. In the Solution properties, select Project Dependencies and then set Project T depends on Project A.
To dynamically link you need to use the A.LIB file as #ajay said. The __declspec(DllImport) tells the compiler what functions and data you are importing but doesn't tell it where you are importing those things from.
Using the A.LIB file as input to the linker is much the same as using the foo.obj file in the statically linking case except that the lib file ends up in the solution output directory <solutiondir>\Debug instead of the project intermediate directory <solutiondir>\A\Debug.
This walkthrough on creating and using a DLL might be useful background.
I asssume project A is DLL not an EXE, which is successfully producing a LIB file.
You need to use the A.LIB as Linker Input in project B. Just producing LIB file wont make other projects automatically link to it.

VC++ resources in a static library

Is it possible to build resources into a static library and reuse them by simply linking with the library?
I'm primarily thinking about the case where you call a function in the library which in turn accesses resources.
The only thing you need to do to use resources (images, dialogs, etc...) in a static library in Visual C++ (2008), is include the static library's associated .res file in your project. This can be done at "Project settings/Linker/Input/Additional dependencies".
With this solution, the resources of the static library are packed into the .exe, so you don't need an extra DLL. Regrettably, Visual Studio does not include the .res file automatically as it does for the .lib file (when using the "project dependencies"-feature), but I think this small extra step is acceptable.
I have looked for a very long time for this solution, and now it surprises me it is that simple. The only problem is that it is totally undocumented.
It can be done, but it's quite painful: You can't do it by simply linking with the static library.
Consider this: resources are embedded in an EXE or DLL. When some code in the static library calls (e.g.) LoadIcon, it'll get the resources from the EXE or DLL that it's linked with.
So, if your static library requires resources to be available, you've got a couple of options:
You can have the library build them on the fly, and then use (e.g.) CreateDialogIndirect. See Raymond Chen's "Building a dialog template at run-time".
You can have them embedded in the library as simple arrays (i.e.) char my_dialog_resource[] = { .... };, and then use (e.g.) CreateDialogIndirect. You'll probably need to find (or write) a utility that converts from .RES files to .CPP files.
You can ship the LIB file with a resource script (.RC file) and corresponding header file. You then #include them as relevant. You'll need to reserve a range of resource IDs for the LIB to use, so that they don't collide with those of the main EXE or DLL. This is what MFC does when used as a static library. Or you can use string resource IDs (this doesn't work for STRINGTABLE resources).
Your static library can ship with a separate resource DLL.
I just went through this with the MS Visual Studio compiler. We were converting some legacy projects from DLLs into static libraries. Several of these DLLs had dialog or string resources embedded in them. I was able to compile the .RC scripts for these DLLs into our main application by including them in the main application's RC script file via the "TEXTINCLUDE" mechanism. I found it easiest to do this by editing the RC file directly, but Visual Studio provides a slightly more "wizardy" mechanism as well. The implementation is most likely different in other compilers.
To manipulate the main RC script directly:
.1. In the "2 TEXTINCLUDE" section, include the header file that defines the resource IDs for your library. The syntax is
2 TEXTINCLUDE
BEGIN
"#include ""my_first_lib_header.h""\r\n"
"#include ""my_second_lib_header.h""\0"
END
.2. In the "3 TEXTINCLUDE" section, include the RC script from your library.
3 TEXTINCLUDE
BEGIN
"#include ""my_first_library.rc""\r\n"
"#include ""my_second_library.rc""\0"
END
Steps 3 and 4 should happen automatically, but I found it was more reliable to just enter them myself, rather than depending on Microsoft's resource script compiler to take care of things.
.3. Add the header file with your libraries resource defines to the read only symbols list. This list is usually near the top of the file.
#define APSTUDIO_READONLY_SYMBOLS
#include "my_first_lib_header.h"
#include "my_second_lib_header.h"
#undef APSTUDIO_READONLY_SYMBOLS
.4. Include your library's RC script in the APSTUDIO_INVOKED section. This is usually at the bottom of the file.
#ifndef APSTUDIO_INVOKED
#include "my_first_library.rc"
#include "my_second_library.rc"
#endif
You can also do all of this automatically through the visual studio IDE, but I found it didn't always apply when I expected it to.
Open the "Resource View" window in Visual Studio.
Right-click on your main application's resource file and choose "Resource Includes..." from the context menu.
In the box labeled "Read-only symbol directives," add the include statements for the .h files that define the resource ID's for your libraries.
In the box labeled "Compile-time directives," add the include statements for your library's .rc script.
Click okay. You may also want to manually trigger the RC script compilation, to make sure it happens.
If your library's resource script references any files on disk (text files, icons files, etc.), you'll need to make sure that the main application project knows where to find them. You can either copy these files to somewhere your application can find them or you can add an additional include path in the compiler settings.
To add an additional include path:
Open up the properties dialog for your main application.
Select "Configuration Properties/Resources/General" from the left-hand navigation pane.
In the properties list, Enter any pertinent paths next to "Additional Include Directories."
As per Visual Studio 2010, the development tools from Microsoft apparently cannot properly handle compiled resource data inside static libraries at all.
To distribute a compiled resource file (a .res file), you have two choices:
Distribute the .res files separately, and instruct the client code to link against them;
Use cvtres to merge several .res files into a single object (.obj) file, and provide it separately.
Note that you can't lib in object files created with cvtres. If multiple object files are provided, lib complains as though as multiple .res files were given; if a single object file is provided, lib does not complain, but the linker simply ignores the embedded resource data in the lib file.
It might be the case that there is a way to force the linker to read and link the libbed in resource data (with some command-line option, section manipulation and so on), since the resource data is indeed available in the library (as dumpbin reveals). So far, I haven't found a solution, and, unless one is willing to hack the development tools, anything better than this simple solution is probably not worth the effort.
The only way to ship resource data in a static library (in this case, with a static library) is to distribute the resources separately and explicitly link them in the client code. Using cvtres can reduce the number of distributed resource files to one, if you have many of them.
I don't think so. Static library doesn't have it's own HINSTANCE. It's code is executed in the context of DLL or EXE which links it. That's why all the resources you'll try to load from the static library's code will be of that enclosing DLL/EXE.
I did that kind of resources reuse with a DLL though, as far as it has it's own address space, and you can call LoadResource with DLL's HINSTANCE.
The recommended way is to provide a dll with the resources together with your library.
When the following method is used, any resource (in this example, an icon) can be used as an integral part of a static library and such library can be used by any type of application, including a console one (which doesn't have any resource segment whatsoever).
Icon is converted to a static array of BYTE. bin2c can be used for that.
Data is converted into a HICON handle. Here is how I have done that:
HICON GetIcon()
{
DWORD dwTmp;
int offset;
HANDLE hFile;
HICON hIcon = NULL;
offset = LookupIconIdFromDirectoryEx(s_byIconData, TRUE, 0, 0, LR_DEFAULTCOLOR);
if (offset != 0)
{
hIcon = CreateIconFromResourceEx(s_byIconData + offset, 0, TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
}
return hIcon;
}
GetIcon is used instead of LoadIcon.
Instead of calling:
m_hIcon = ::LoadIcon(hInstanceIcon, MAKEINTRESOURCE(pXMB->nIcon));
Then call
m_hIcon = GetIcon()

Resources