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?
Related
I've got 2 C++ project in the same Visual Studio solution: Engine, a library; and Test, that uses the Engine library
Engine compiles correctly on Windows and produces a lib and a dll. The lib is correctly given to the linker of Test as well
In Test, I try to import a module from Engine, but the compiler fails with error C2230
Here are code excerpts from the 2 projects:
Engine > hal.ixx
export module hal;
#ifdef TEST_ENGINE_EXPORTS
#define TEST_ENGINE_API __declspec(dllexport)
#else
#define TEST_ENGINE_API __declspec(dllimport)
#endif
import <string>;
export extern TEST_ENGINE_API void prepareMain();
export extern TEST_ENGINE_API int init();
//...
Test > main.cpp
#include <cstddef>
#include <stdio.h>
import hal; //fails here: error C2230 could not find module 'hal'
int main(int argc, char const* argv[])
{
prepareMain();
// some other stuff...
}
I'm using Visual Studio 2022 (v. 17.4.0), and for the 2 projects, I compile with std::c++latest, /permissive- and /experimental:module. I've also added the Engine header's folder as Additional include directory for the Test project.
I've tried to remove the module altogether and including headers files in Test and functions are correctly called
I already read this question (How to import a c++ module from another library?) that has the same problem that me, and the article linked in one comment (VS2019 Modules), but I fail to see how it can solve my problem
EDIT
So, I ran a couple of tests, and basically, it seems to stem from the fact that my library is a dll project
I tried making a new solution with 2 projects
The library one is a WindowsStaticLib project. Compiler options are : /std:c++latest, /std:c17, /permissive-, /experimental:module, and /sdl and /W3 (last 2 where there by default, I let them as they were). I deactivated precompiled headers since it seemed to interfere with modules (compliling amodule unit with /exportHeader as it is recommended here when module import standard header was causing VS to start looking for pch.h in header)
For the actual project using the library; library project is added as a reference, compiler options are the same as the library project, lib headers directory is added to VC++ directories > External include directories, lib folder to Library directories, and .lib file added as an Additional dependancy
Everything works.
Module is correctly found and imported, and functions can be called from the actual project.
As a side note, I should add that I didn't need to specify my module functions as extern for them to be usable in the other project main.cpp. I thought I should have done it but apparently not.
Now I tried to do the same thing but with a DLL project for the library. New solution with 2 project, with the exact same configuration as it was for the previous solution.
Error C2230 when I try to import my module in the actual project main.cpp.
Does anyone know something about this ?
Is it normal behaviour that I just didn't know ?
I want to create a dll that exports a function and a struct. I went through the walkthrough and here is what I have:
Project myDll: the_dll.h
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
typedef struct MyStruct
{
bool b;
} MYSTRUCTTYPE, *PMYSTRUCTTYPE;
typedef const MYSTRUCTTYPE *MYCSTRUCTTYPE;
MYDLL_API bool dllF();
Project myDll: the_dll.cpp
#include the_dll.h
bool dllF() { return true };
In the Preprocessor definitions of the myDll project, I define MYDLL_EXPORTS
In Linker -> Advanced -> Import Library I see $(OutDir)$(TargetName).lib
Yet there is no lib generated, only dll and pdb
Intellisense shows MYDLL_EXPORTS to be __declspec(dllexport) and the dllimport portion is grayed out... So I must be exporting...
I have included the dependent header file, and set the additional library directories and additional include directories, as well as dependent libs, in the caller project. But... in the absence of the lib...
The project that requires the functions from this dll gives unresolved external symbol error.
How can I make my dll create a lib ? What am I missing ? (Or... how can I use its functions without linking to a lib and include a header ?)
Note: I assume the structs and typedefs do not need to be exported... true ?
Update: as I wrote in comment, the project did create a lib when I imported it into a different solution and erased all the debug folders... I have been "Build -> Clean Solution" between tries but I suppose something did not get cleaned ...
So the true reason for not getting a lib created was (my guess) that, while experimenting with the code and before adding the definition for MYDLL_EXPORTS, files where created that did not get cleaned... I will always delete the build folders before trying again, in the future.
I checked with a small test project in VS2013. It produced .lib files for both my DLLs in the Debug directory. This means that if the setup is not screwed up, using default settings you should have implib after building the DLL.
In fact, you need .lib file only if you want to distribute your dll to customers. If you want to use this dll in the same solution by other projects, do the following:
Select project where you want to import functions.
On the top menu click PROJECT->References....
Click button "Add New Reference" at the mid bottom.
Select dlls that you want to import from.
Close all dialogs with OK.
Rebuild your solution.
Structures cannot be exported. They are communicated to other binaries using header files. You can export only function entry points (including class member functions) and static data fields. You should include your header both into your dll code and and all applications that use your DLL. The #ifdef MYDLL_EXPORTS has exactly this purpose.
After a day of banging my head against the wall both literally and metaphorically, I plead for help:
I have an unmanaged C++ project, which is compiled as a DLL. Let's call it CPP Project. It currently works in an unmanaged environment. In addition, I have created a WPF project, that shall be called WPF Project. This project is a simple and currently almost empty project. It contains a single window and I want it to use code from Project 1. For that, I have created a CLR C++ project, which shall be called Interop Project and is also compiled as a DLL.
For simplicity I will attach some basic testing code I have boiled down to the basics.
CPP Project has the following two testing files:
tester.h
#pragma once
extern "C" class __declspec(dllexport) NativeTester
{
public:
void NativeTest();
};
tester.cpp
#include "tester.h"
void NativeTester::NativeTest()
{
int i = 0;
}
Interop Project has the following file:
InteropLib.h
#pragma once
#include <tester.h>
using namespace System;
namespace InteropLib {
public ref class InteropProject
{
public:
static void Test()
{
NativeTester nativeTester;
nativeTester.NativeTest();
}
};
}
Lastly, WPF Project has a single window refrencing Interop Project:
MainWindow.xaml.cs
using System;
using System.Windows;
using InteropLib;
namespace AppGUI
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InteropProject.Test();
}
}
}
And the XAML itself has an empty window (default created).
Once I am trying to run the WPF project, I get the following error:
System.Windows.Markup.XamlParseException: 'The invocation of the constructor on type 'AppGUI.MainWindow' that matches the specified binding constraints threw an exception.' Line number '3' and line position '9'. ---> System.IO.FileNotFoundException: Could not load file or assembly 'InteropLib.dll' or one of its dependencies. The specified module could not be found.
at AppGUI.MainWindow..ctor()
Interestingly enough, if I do not export the class from CPP Project, I do not get this error. Say, if i change tester.h to:
#pragma once
class NativeTester
{
public:
void NativeTest()
{
int i = 0;
}
};
However, in this case I cannot use my more complex classes. If I move my implementation to a cpp file like before, I get unresolved linkage errors due to my not exporting my code. The C++ code I want to actually use is large and has many classes and is object oriented, so I can't just move all my implementation to the h files.
Please help me understand this horrific error I've been trying resolve without success.
Thanks.
This went wrong right from the start, your tester.h file is not correct. The class should only have the __declspec(dllexport) attribute when you are building the tester project. Any other project that uses the DLL must see the class with the __declspec(dllimport) attribute. Start fixing this by using a macro in tester.h:
#undef EXPORTED
#ifdef BUILDING_DLL
# define EXPORTED __declspec(dllexport)
#else
# define EXPORTED __declspec(dllimport)
#endif
class EXPORTED NativeTester {
// etc..
};
And in your tester project, use C/C++, Preprocessor, Preprocessor Definitions and add BUILDING_DLL.
Next thing is to make sure that the DLL is being stored in the right directory. Which is what the exception is complaining about, it can't find the DLL. The build directory for C++ projects is Debug but for WPF projects it is bin\Debug. Fix that by changing the General + Output Directory setting, make it $(SolutionDir)$bin\(ConfigurationName).
Build the C++ project and verify that you can find the DLL back in the Solution's bin\Debug directory. And check that you also have the .lib file, you'll need that when you build the C++/CLI project. As an extra verification step, run Dumpbin.exe /exports foo.dll from the Visual Studio Command Prompt and check that you indeed see the class getting exported.
The C++/CLI project next, you need to change the Output Directory setting the same way. Add the .lib file to the linker's Additional Dependencies properties. You'll get the kind of linker errors you were talking about if you skip that step. Build it and verify that you get the DLL in the correct bin\Debug directory again.
Repeat these changes for the Release configuration.
Set the project dependencies, the WPF project depends on the C++/CLI project. The C++/CLI project depends on the C++ project. This ensures the projects are getting built in the right order.
You should now have a good shot at using these DLLs in your WPF project.
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 !
Alright, here's the issue. In an attempt to advance my knowledge of C++ APIs, I attempted to learn more about library file types. I have static libraries figured out quite well. You simply link the library into the project, and its contents are placed inside the binaries when it's compiled and linked. But, I hit an issue when I started trying to use dynamic libraries. I was able to successfully compile a DLL file using the __declspec function, and creating extern blocks(so it can successfully be exported to C++). But, the issue arises when I try to link the file. Based on multiple tutorials I have seen across the web, I create a header with forward definitions, and include it into the executable project. Then, I make sure to add the search directory to the project build settings, along with the path to the library I am importing. Then, when I go to build the project, it produces a linker error(I can tell because the object file is compiled) "cannot find -l[path to file]". Are there more configurations to be made? I assume it has something to do with my compiler(MinGW), because Code::Blocks(I'm currently using the Eclipse CDT plugin) produced a similar link error.
If you need to see the code, I will provide it below.
// EXE: main.cpp
#include <iostream>
#include "DLLTutorial.h"
int main()
{
Function();
std::cout << "1 + 3:\t" << Add(1, 3);
}
// DLL: DLLTutorial.cpp
#define DLL_EXPORT
#include <iostream>
#include "DLLTutorial.h"
extern "C"
{
DLLCOMP int Add(int a, int b)
{
return a + b;
};
DLLCOMP void Function(void)
{
std::cout << "DLL Called!\n";
};
};
// DLL: DLLTutorial.h
#ifndef DLLTUTORIAL_H_
#define DLLTUTORIAL_H_
#include <iostream>
#ifdef DLL_EXPORT
#define DLLCOMP __declspec(dllexport)
#else
#define DLLCOMP __declspec(dllimport)
#endif
extern "C"
{
DLLCOMP int Add(int a, int b);
DLLCOMP void Function(void);
};
#endif /* DLLTUTORIAL_H_ */
It's just very simple example code I used from a website. I cannot get the executable file to link properly, so I would appreciate any advice that could be given to me.
Also, I have a related question. Reading a few of the tutorials online, some made mention about the __declspec function being Windows/Microsoft specific. Is this true? In which case, what would be a nice equivalent to use on other operating systems?
When you build a dll you also create a companying .lib file, the 'implib'. You must statically link this file in your exe.
EDIT: __cdeclspec(...) is indeed Microsoft. Dont't know about other platforms.
You need to tell the compiler where to search for your libraries and includes. In both GCC and MinGW this is achieved by using -I for includes, and -L for libraries. I don't think its necessary for you to generate the .lib (or .a as it usually is in *nix and GCC), GCC should be able to find your function in the dll.
For example, build and link the shared lib:
g++ -shared -olibmy_dll.dll my_dll.cpp
Then, assuming all the files are in the same dir, build and link the exe and tell GCC to use your lib:
g++ -oapp.exe app.cpp -lmy_dll -L.
Note the difference between -l and -L, one tells GCC what libs to use, while the other tells where to look for them. In Eclipse CDT you find these settings in: Project properties -> C/C++ Build -> Settings -> MinGW C++ Linker -> Libraries.
Also, __declspec is recognized by MinGW, but I think its Microsoft specific anyway.