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.
Related
I got the error undefined reference to 'luaL_newstate' when I try to build my project. I know it's an error with the linker but I'm relatively new to Lua and adding a library to a project. I use Code::Blocks by the way. API functions luaL_openlibs, luaL_loadfile, lua_pcall, lua_getfield, lua_type, lua_settop are missing too.
I saw on a webite that I have to link my project with libdl in order to solve this problem, but I don't really know what it mean and how to do it.
I faced the same problem, in my case I found a solution that worked for me here. Basically consist in wrapping the #include s of lua inside a extern "C", like:
extern "C"{
#include <lua5.2/lualib.h>
#include <lua5.2/lauxlib.h>
#include <lua5.2/lua.h>
}
Lua can be a bit complex when you're first trying to compile it. The website that you referenced was correct: libdl is pretty much required when linking Lua.
I don't have Code::Blocks in front of me, so I can't really tell you what options you need to add. It should be a list of "command line options" or "compiler options". If you were compiling from the command line, the full command would look like:
gcc -o sample sample.c -llua -ldl
Note that the -l options have no space before the library name. There should be an option in Code::Blocks to add your own compile-time options or compiler flags. You would add "-llua" and "-ldl" to that options list. Alternatively, just do it yourself from the command line.
libdl is a library that is used when dynamically linking other libraries into your program. You have to add it in for Lua to be linked correctly.
As the accepted answer mentioned, these headers lack of extern "C". An alternative is to include the installed lua.hpp, which already use extern "C" to wrap these Lua headers.
// lua.hpp
// Lua header files for C++
// <<extern "C">> not supplied automatically because Lua also compiles as C++
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
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?
I created by the first time a dll to use with C++ (and then C#, I have plans to share this dll between a C++ and C# applications) using QT creator but when I try to use it I get SEGFAULT error.
Here's my files:
mydll.h
#ifndef MYDLL_H
#define MYDLL_H
#include "mydll_global.h"
class MYDLLSHARED_EXPORT MyDll
{
public:
MyDll();
int getAnswer();
};
MYDLLSHARED_EXPORT int getNumber();
#endif // MYDLL_H
mydll_global.h
#ifndef MYDLL_GLOBAL_H
#define MYDLL_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(MYDLL_LIBRARY)
# define MYDLLSHARED_EXPORT Q_DECL_EXPORT
#else
# define MYDLLSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // MYDLL_GLOBAL_H
mydll.cpp
#include "mydll.h"
MyDll::MyDll()
{
}
int MyDll::getAnswer()
{
return 42;
}
int getNumber()
{
return 10;
}
So I build it and created mydll.dll: then I went to other C++ project wheere I want to use this dll and put in the .pro file:
LIBS += "C:\path\to\mydll.h"
and in the main.cpp
#include "mydll.h"
and when I use function from dll like this:
qDebug() << getNumber();
I get a SEGFAULT error.
I thought that the header to provide the compiler type information and the dll to compiler to provide the function body was all I needed but as I'm getting a SEGFAULT I'm acessing NULL or someone else memory or so (I can't see the value on debug).
What am I missing?
First off, to link the DLL you need the link .lib file for that DLL. That file has all the binary manifest for linking.
Second, project file LIBS clause specify the list of .lib files to link with. Some of them may represent dynamic libraries (.dll).
See the example: Linking to Shared Library in Qt
Even better article covering both creation of DLL with Qt and using DLL in your Qt project: https://wiki.qt.io/How_to_create_a_library_with_Qt_and_use_it_in_an_application
I had this same issue. Almost every example I looked at had a class as their example, but I wanted to export functions like getNumber(). It's in the qt5 docs as you probably know by now.
This line needs to be in your header file:
extern "C" MYDLLSHARED_EXPORT int getNumber();
and it is either the mydll_global.h or mydll.h depending on what you are using.
mydll_global.h would be what qtcreator creates and puts export definitions in if you create a new Shared Library project.
I was thrown off guard by the extern "C" part as I wasn't using C and wasn't as familiar with how compilers export symbols.
Trying to add a public static function to a class definition using static MYDLLSHARED_EXPORT int getNumber(); or simply using a namespace (function defined with or without static) will give a not found for architecture x86_64 error using clang on osx.
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.
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