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.
Related
I have a project written en c++ in which i use tesseract and opencv libraries.
the project contain one function which return an Int ant it has as parameter sting an int
int image_blanche(string nom_img,double k);
My question how can i convert it to dll file to use it in an other .net project
Add a header file (e.g. "Defines.h") containing:
#pragma once
#ifdef COREDLL_EXPORTS
#define COREDLL_API __declspec(dllexport)
#else
#define COREDLL_API __declspec(dllimport)
#endif
Your function should then be defined in a header like this:
#include "Defines.h"
extern "C"
{
COREDLL_API int image_blanche(char const* nom_img,double k);
};
...and implemented in a source file.
Compile that Project with COREDLL_EXPORTS defined as a DLL Project and use the dll in another project.
When building the DLL having COREDLL_EXPORTS defined you basically produce (=export) the symbols and place them in the DLL. When using the DLL in another project not having COREDLL_EXPORTS defined, you consuming/reading (=import) the symbols from the DLL.
Here is a good explanation of how you can then invoke the function from the DLL: Dynamic Invoke C++ DLL function in C#
Update: As MSalters correctly pointed out, using C-Style datatypes should be considered, as it plays friendly across DLL bounds. I changed the string parameter to use a character array instead.
I have a package of C functions and I need to create DLL library from it, that can be used in C++ program. I haven't done any library before, so I am total beginner in that. I am working in Qt Creator.
My first try was to create it according to the manual Creating shared libraries, so I added these two lines to my project file:
TEMPLATE = lib
DEFINES += MYLIB_LIBRARY
Then I created mylib.h file
#ifndef MYLIB_H
#define MYLIB_H
#include "mylib_global.h"
#include "functions1.h"
#include "functions2.h"
#include "functions3.h"
class MYLIBSHARED_EXPORT Mylib
{
public:
Mylib(){};
};
#endif // MYLIB_H
Finally I added mylib_global.h:
#ifndef MYLIB_GLOBAL_H
#define MYLIB_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(MYLIB_LIBRARY)
# define MYLIBSHARED_EXPORT Q_DECL_EXPORT
#else
# define MYLIBSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // MYLIB_GLOBAL_H
To make functions usable in C++ I used these lines for each function in library
#ifdef __cplusplus
extern "C"{
#endif
void foo();
#ifdef __cplusplus
}
#endif
When compiling with MSVC2012 everything seems ok and I got some .dll file. But then I sent library to someone, who wanted to use it in Borland C++. He told me that I have to compile it with some DEF file to tell to VS compiler right names and with __stdcall instead of __cdecl. But I have no idea how to do it in Qt. Any explanation and help would be really appreciated. Thanks
P.S. I looked at posts Using VS dll in old Borland and Import VS dll in C Builder, but they
did not help me to understand the problem.
If you want to export the foo function, you need to tell the linker somehow.
What you were suggested is to use a .def file, which is quite easy.
Just create a file like exports.def in your project directory, and write in it something like:
EXPORTS
foo
Then go to your library project settings -> Linker -> Input -> Module Definition File
and fill in your .def file name
I am having trouble with a dll I am writing in C++. There is some very strange behavior going on that I have not been able to solve on my own.
It's hard to describe exactly what's going on, but I will try my best. Basically I have a class in my DLL with a single private property and a public constructor. When I initialize this class and then exit the program I get an error.
"Run-Time Check Failure #2 - Stack around the variable 'test' was
corrupted"
I have 2 projects here:
The DLL named "testdll".
The console test program named "test".
I have boiled this error down to its simplest reproducible form to try and narrow down the possible causes, below you will find my code.
Project "testdll", file testdll.h:
#include <string>
class testdll
{
public:
__declspec(dllexport) testdll(); // Empty but same error if prams are used.
private:
std::string _var;
};
Project "testdll", file testdll.cpp:
#include "testdll.h"
testdll::testdll()
{
}
Project "test", file testdll.h:
#include <string>
class testdll
{
public:
__declspec(dllimport) testdll();
};
Project "test", file stdafx.h:
#pragma once
#include "targetver.h"
#include <tchar.h>
Project "test", file test.cpp:
#include "stdafx.h"
#include "testdll.h"
int _tmain(int argc, _TCHAR* argv[])
{
testdll test;
return 0;
}
If you want I can send you the Visual C++ 2010 solution file, in the archive format of your choice. Please help! I have no idea what's going on.
Optional Information:
Language (or Software): C++
Already Tried:
Deleting the constructor definition, which works but is not a usable solution, nor does it explain the problem. Also making all of my private properties into pointers works, however I should not have to do this.
You are using two header files, they don't declare the same class. One has a std::string member, the other doesn't. That's very very bad, the compiler doesn't reserve enough space for the object on the stack frame. Which is what the runtime error is telling you. Very nice feature btw, this kind of mistake is incredibly hard to diagnose otherwise.
You probably got into this pickle because you only applied __declspec(dllexport) to the constructor instead of the entire class. You'll need to write the header file so it can be used by both your dll project and your exe project. That should look like this:
#undef DLLEXPORT
#ifdef BUILDING_MYDLL
# define DLLEXPORT __declspec(dllexport)
#else
# define DLLEXPORT __declspec(dllimport)
#endif
class DLLEXPORT testdll
{
public:
testdll();
private:
std::string _var;
};
Right-click your DLL project, Properties, C/C++, Preprocessor, Preprocessor Definitions. Append BUILDING_MYDLL
And delete the testdll.h file in your exe project directory. Set the C/C++, General, Additional Include Directories setting so the compiler can find the header in the testdll project directory (like ..\testdll)
Exporting classes and class members from a DLL is very VERY fragile, as you have just discovered. If the library and client don't both use the exact same class layout, which depends on all kinds of compiler settings, things fail horribly.
In your case, you're probably using incompatible versions of std::string inside class testdll. Maybe one is compiled for debug and one for release. Or one is using the static runtime library and the other the DLL runtime. Who can say?
Anyway, as soon as you export C++ features from a DLL, you lock yourself in to that compiler version and settings. It's a maintenance nightmare.
Use v-table-only base classes or C-compatible wrapper functions.
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.
I want to bring a .dll dependency into my Qt project.
So I added this to my .pro file:
win32 {
LIBS += C:\lib\dependency.lib
LIBS += C:\lib\dependency.dll
}
And then (I don't know if this is the right syntax or not)
#include <windows.h>
Q_DECL_IMPORT int WINAPI DoSomething();
btw the .dll looks something like this:
#include <windows.h>
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
extern "C"
{
int WINAPI DoSomething() { return -1; }
};
Getting error: unresolved symbol?
Note: I'm not experienced with .dll's outside of .NET's ez pz assembly architechture, definitely a n00b.
Your "LIBS +=" syntax is wrong. Try this:
win32 {
LIBS += -LC:/lib/ -ldependency
}
I'm also not sure if having absolute paths with drive letter in your .pro file is a good idea - I usually keep the dependencies somewhere in the project tree and use relative path.
EDIT:
I suppose that something is wrong in your dll, i.e. the symbols are not exported correctly. I always use template provided by QtCreator:
Inside dll project there is mydll_global.h header with code like that:
#ifdef MYDLL_LIB
#define MYDLL_EXPORT Q_DECL_EXPORT
#else
#define MYDLL_EXPORT Q_DECL_IMPORT
#endif
Dll project has DEFINES += MYDLL_LIB inside it's pro file.
Exported class (or only selected methods) and free functions are marked with MYDLL_EXPORT inside header files, i.e.
class MYDLL_EXPORT MyClass {
// ...
};
This is possible if the DLL contains files with a "C" linkage (i.e. no C++ class decorations) and if you have a header file and a .def file for the DLL. If you do not have a .def file you can create one easily by downloading the dependency walker tool from http://www.dependencywalker.com/ to get the list of exported symbols; you can save the output of this tool as text, then extract the names. You then create a text file called mylibname.def that holds:
LIBRARY mylibname
EXPORTS
FirstExportedFunctionName
SecondExportedFunctionName
...
LastExpertedFunctionName
Then you run dlltool (in MinGW\bin):
dlltool -d mylibname.def -l mylibname.a
This will generate mylibname.a, which you add into your .pro file:
win32:LIBS += mylibname.a
You have to provide paths to all the files, or copy them to the right folders, of course.
You must also modify the header file to your third party program so that all the symbols in the DLL that you need to link to are marked for import with Q_DECL_IMPORT. I do this by
declaring all functions in the .h file as:
extern "C" {
MYLIBAPI(retType) FirstFunctionName(arg list...);
MYLIBAPI(retType) SecondFunctionName(arg list...);
...
MYLIBAPI(retType) LastFunctionName(arg list...);
}
where MYLIBAPI is
#define MYLIBAPI(retType) Q_DECL_IMPORT retType
We use the MYLIBAPI(retType) format as this allows us to adjust the header file for use in both import and when creating DLLs and it also allows us to work with a wide variety of different compilers and systems.
Doing this, I managed to link QT in MinGW to a DLL that I generate using VS 2005. The routines in VS were exported as __stdcall. You should look at the dlltool documentation for adding underlines or other prefixes to the names in the library.
You need to make the function's declaration available to the linker as well as providing the path to the dll in which it's located. Usually this is done by #including a header file that contains the declaration.
You also don't need the Q_DECL_IMPORT macro in the client - this would be used in a Qt library's header to allow client apps to import the function. A class or function would be conditionally exported/imported depending on whether the library or a client is being built. More info can be found on this page.
Is your dependency a third party dll or something that you've created?