I would like to build two C++ projects in the same solution in Visual Studio 2010 that can interact with each other. I have created a solution under directory C:\Users\me\Desktop\SolutionDir. The two projects have been created respectively under C:\Users\me\Desktop\SolutionDir\FirstProject and C:\Users\me\Desktop\SolutionDir\SecondProject.
My first project contains two files, a header function.h and a cpp file function.cpp
function.h
#pragma once
void print_stuff();
function.cpp
#include "function.h"
#include <iostream>
void print_stuff() {
std::cout << "hello world" << std::endl;
}
My second project contains the main file main.cpp
main.cpp
#include "FirstProject\function.h"
#include <iostream>
int main(void) {
print_stuff();
int stop;
std::cin >> stop;
return 0;
}
I added the directory C:\Users\me\Desktop\SolutionDir\ in my SecondProject Configuration Properties > C/C++ > General > Additional Include Directories. I still get the classical error : error LNK2019: unresolved external symbol when calling the function print_stuff().
Any ideas ?
Try building the first project as a Static Library in Project Properties/Configuration Properties/General/Configuration Type.
Then in your project properties for the second project, you'll need to change two things:
In Linker/General, you might need to add to "Additional Library Directories" the folder where the first project's .lib is built.
In Linker/Input, you will need to add to Additional Dependencies the name of the .lib file like FirstProject.lib or whatever its name is.
Yes, you need to export the functions using _declspec(dllexport) and import them in the project that calls the functions with _declspec(dllimport).
This duality is usually achieved with a macro:
#pragma once
#ifdef FIRST_PROJECT_BUILD
#define IMPEXP _declspec(dllexport)
#else
#define IMPEXP _declspec(dllimport)
#endif
IMPEXP void print_stuff();
In the configuration of your first project, you add FIRST_PROJECT_BUILD to your preprocessor directives. That way, when you compile first project, you tell the compiler the function is to be exported. However, when you include the file in a different project, that doesn't have FIRST_PROJECT_BUILD defined, you tell the compiler the function is implemented in a different library and should be imported.
Also, besides adding the extra include paths, you need to add the generated .lib files from the projects implementing the functions to the Extra dependencies tab in the Liner settings of your project configuration.
You can include a realPath for you include directory !
Like for your FirstProject include "./../"
And the same include dir for your second Project like that you can move or copy your directory SolutionDir and it will always work !
For your unresolved linked you have to add the function.cpp and function.h in your First and Second Project
You can place it in SolutionDir!
Like that You always have two files for your first and second project instead of four !
Hope it helps !
Related
I am just beginning to learn C++ and using Visual Studio 2017 as the IDE. I want to stay away from the CLR, and even Windows specific code as much as possible. Every new project option seems to say 'Windows', and thus suggest Windows OS dependencies, except for General > Empty Project, so that is the option I have chosen.
I am trying to write a static library with some functions. Here's a simple example of what I'm trying to do.
//Lib1.h (Project A)
#pragma once
#ifndef LIB_H
namespace Lib1
{
double Add(double, double);
}
//Lib1.cpp (Project A)
#include "Lib1.h"
namespace Lib1
{
double Add(double a, double b)
{
return a + b;
}
}
//Main.cpp (Project B)
#include "Lib1.h"
using namespace Lib1;
int main()
{
double c = Add(1, 2);
}
Project A compiles without warning/error. I changed the Project Properties > General > Configuration Type to be Static Library (.lib), but I cannot actually find the compiled .lib file in the project directory, just an .obj file.
When I try and build Project B it throws the following error message.
"LNK2019 unresolved external symbol "double __cdecl FrameTransformations::Add(double,double)" (?Add#FrameTransformations##YANNN#Z) referenced in function _main FrameTransformationTests S:\Projects\Cpp\Code\FrameTransformations\FrameTransformationTests\Main.obj 1"
I've had a look and it seems that project B can't find the Add function from project A, although I get auto-completion for the function and arguments through Intellisense (is this just because it can find the Lib1.h file ok?).
I have tried adding in the path to the Project A folder in the Project B Properties > C/C++ > General > Additional #using Directories (both to the Project folder and to the Debug folder where I expected the Lib1.lib file to be generated), but that hasn't worked.
Can someone please point me to what I've done wrong, this has had me stumped for a couple of hours now.
Thank you.
The .lib file is generally under the solution directory rather than the more specific project directory:
Look in \ or possibly \\.
When you #include a .h file, you are usually just including declarations into your code (exceptions apply, but not in this case). These are separate from definitions which are placed into .cpp files.
By default your projects do not automatically shared any of this information with each other. Your definitions nor declarations from Project A do not magically propagate to Project B, for example.
But as you've done here, you can reference declarations from Project A into Project B by #includeing header files. These, however, are just declarations! They just explain the existence of a function but don't implement it -- You need to add the definition of your Add function to Project B.
The process of bringing such definitions together is called linking. You need to link the definitions of Project A (the .lib, more precisely) into Project B. The way you do this changes with each version of Visual Studio just slightly, but it's usually under some "Linker Options" and some "Dependencies" tab/window.
You need to add reference of Project A into Project B->Project Properties as below,
Also, you need to add a reference in like below
I created a DLL project called Test Lib:
// main.h
#ifndef __MAIN_H__
#define __MAIN_H__
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
extern "C" {
DLL_EXPORT void print();
}
#endif
// main.cpp
#define BUILD_DLL
#include "main.h"
#include <iostream>
using std::cout;
using std::endl;
extern "C" {
DLL_EXPORT void print() {
cout << "Success" << endl;
return;
}
}
The library builds successfuly, and I then created a console project called TestApp:
// main.cpp
#include <main.h>
int main() {
print();
return 0;
}
Test Lib and TestApp folders are both in C:\Documents and Settings\user\Desktop\Practice Projects
On Code::Blocks -> Global compiler settings -> Search directories,
Compiler has added C:\Documents and Settings\user\Desktop\Practice Projects\Test Lib
Linker has added C:\Documents and Settings\user\Desktop\Practice Projects\Test Lib\bin\Debug
In TestApp -> Build options -> Linker settings, Link libraries has added Linker has added C:\Documents and Settings\user\Desktop\Practice Projects\Test Lib\bin\Debug\libTest Lib.dll.a
When I try to run the program, I get "TestApp.exe - Unable to Locate Component"
This application has failed to start because Test Lib.dll was not found. Re-installing the application may fix this problem.
main() returns 0xC0000135. This is the second DLL library I have ever created, and is because I encountered the same error in my first library and I am trying to replicate the error.
In one attempt, I tried to change the .dll.a link to a relative path. In another attempt, I moved the compiler and linker directories down to project-level rather than global level, all three paths in absolute format. In a third attempt, I did the same but with all three paths in relative format. None of these work, and give the same error.
What's going wrong?
Edit: Someone said in comments I need to add the DLL path to system settings. I don't understand what I need to do when he says that. I was following this tutorial on creating and using DLL, which says I needed to add the .lib and .dll to the project path, which is what I did as described above after doing more searching (Code::Blocks isn't my usual IDE, my employer gave it to me for temporary use). When I created my first DLL 2 days ago, that was all I did and everything worked. Then, I added a new function for checking if an integer is a prime. Yesterday morning, I came back to work and the DLL doesn't work anymore. I have been trying to figure out the problem until now, because I had not done anything to cause it to stop working (I literally only added the function, turned the computer, left work and returned the next day, then rebuild the DLL project and ran the console app project). Now, I tried searching on how to add a DLL path to system settings, and I don't see any results relevant to C++ and/or Code::Blocks that looks like the answer. Can someone tell me what I'm supposed to be looking for?
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.
My objective is to create a dll and lib file so i'm following this guide
1) I created a new win32 Console Application project in VS, chose DLL as 'Application Type' and Emptied Project
2) I'm trying to create a database in C++. So I have 5 headers with ONLY function declarations.
3) Database.h is my top header, it looks like this:
#ifdef DBDLL_EXPORTS
#define DBDLL_API __declspec(dllexport)
#else
#define DBDLL_API __declspec(dllimport)
#endif
#ifndef __Database_H
#define __Database_H
#include "Table.h"
class DBDLL_API Database { ... };
#endif
4) Now with only headers, I tried compiling the project. It compiled but I don't see any DLLs or Libs anywhere in the project folder. How do I create them?
This is because headers are not compiled -- only CPP files are compiled (which pull in the headers -- a source file and all the headers it pulls in is called a "translation unit", which is the thing actually being compiled (independent of other TUs)).
So, in effect, the build system thinks you're building an empty project, and in this case generates nothing at all. Note that even if the headers are pulled in and compiled, unless an exported symbol is actually referenced somewhere, it may be optimized out. In such cases, you will get an (empty) DLL, but no .lib file (which can cause errors down the line if you have dependent projects looking for this .lib before there's anything in the DLL).
You'll need to create some CPP files that implement the functions declared in the headers. If you have everything in the headers and don't need any CPP files at all, then there's no point in having a DLL! (Since you could include the headers in any other project without needing any other dependency.)
Finally, your include guard (#ifndef ...) should encompass the entire header, including the DLL export macros, otherwise you'll eventually get macro redefinition warnings.
I would suggest using #pragma once instead of include guards since it's simpler and recognized by pretty much every compiler. I would also put the DLL macro goop into its own header (e.g. "dllmacros.h") and include that where it's needed (this will reduce duplication).
I am trying to create an application in visual studio that will be able to access a .dll file that already exists. I need the application to call up routines. I also have a header file that already exists.
I have been researching on the internet and have found that I need to create a .lib file. Looking at similar questions on here I found a link: http://support.microsoft.com/kb/131313
I cannot however follow the directions.
The information in the link says to make a DEF file ( I read elsewhere that this needs to be compiled as a DLL with the same name, but not sure what that name is, the same name as the .dll file?). But I do not understand the first direction, to 'Use DUMPBIN /EXPORTS'. I then need to 'stub out' functions, and then something to do with .OBJ files (I do not know what these files are).
Are there any step-by-step directions, similar to the link above, that are easy to follow?
You're going to need Microsoft Visual C++ 2010 Express (or any other source of MSVC command line tools), and your DLL.
Steps:
dumpbin /EXPORTS yourfile.dll > yourfile.exports
Paste the names of the needed functions from yourfile.exports into a new yourfile.def file. Add a line with the word EXPORTS at the top of this file.
Run the following commands from VC\bin directory (the one where lib.exe and other compile tools reside).
vcvars32.bat
lib /def:yourfile.def /out:yourfile.lib
or for x64 builds
lib /def:yourfile.def /machine:x64 /out:yourfile64.lib
You should get two files generated: yourfile.lib and yourfile.exp
You can use Digital Mars's IMPLIB tool. It can create a lib file using only the dll, without any need for a .def file.
The download link is http://ftp.digitalmars.com/bup.zip.
The command line is:
implib.exe /s mydll.lib mydll.dll
There is a much simpler way to create a .def file. Search the web for the gendef utility (you may already have it if you have Mingw-64). Once you have it, just go to a command line and type,
gendef myfile.dll
And it will create a myfile.def. After that, just use lib.exe to create the myfile.lib file as explained by John.
Here is a solution using Cygwin:
install gendef and mingw64-x86_64-binutils Cygwin packages
run in Cygwin console:
gendef.exe awesome.dll
x86_64-w64-mingw32-dlltool.exe -d awesome.def -l awesome.lib
you get awesome.lib in the same dir.
VS 2019 linker linked just fine using this file.
I might have the answer. I did this when I was creating a .exe console application that needed a .dll file. I ran into the problem as well. When I tried the IMPLIB application, it couldn't find any export files. You need to add an #ifdef FILENAME_EXPORTS (replace FILENAME with your .dll file name) and create an _API. Here is the code for the #ifdef export api commands:
#ifdef FILENAME_EXPORTS
#define FILENAME_API __declspec(dllexport)
#else
#define FILENAME_API __declspec(dllimport)
#endif
Now that you have the Export API defined, you need to apply it to all the functions in your header file in the .dll project. For example:
void FILENAME_API function();
Declare your export functions normally, but include the API between the declarer type and the function name.
For defining the function in the .cpp file in the .dll project, you don't need the API in the declaration.
Here is an example of filename.h and filename.cpp with all the code.
// Code for filename.h
#pragma once
// Define your Export API
#ifdef FILENAME_EXPORTS
#define FILENAME_API __declspec(dllexport)
#else
#define FILENAME_API __declspec(dllimport)
#endif
// Declare your functions with your API
void FILENAME_API function1();
void FILENAME_API function2();
void FILENAME_API function3();
-------------------------------------------------------------------------------------------
// Code for filename.cpp
#include <iostream>
#include "pch.h"
#include "filename.h"
using namespace std;
void function1()
{
cout << "Hello Function1!";
}
void function2()
{
cout << "Hello Function2!";
}
void function3()
{
cout << "Hello Function3!";
}
Now when you compile the project, you should see the .dll, .lib, and .exp files in the folder where the compiled files are saved to. Now you can link the .exe file with the .lib file. You're Welcome!
First type
#define YOURPROJECT_API _declspec(dllexport)
void yourf()
cpp
#include "pch.h"
#include "YOURPROJECT.H"
void yourf() {}
then include them
linker->input->def file then inhert from parent or project default
compile