-
Static and Dynamic Libraries
How does Qt differentiate between static and dynamic libraries when both are included in the application pro file? The doc is not clear and the syntax appears to be the same for both. Just by the library file extension (.a Vs .dll on Windows)? I have listed both types in the pro file and the static (<lib>.a) is working but not the dynamic (<lib.dll>) is not and won't load with QLibrary.
-
Re: Static and Dynamic Libraries
The syntax is the same. The .a library basically contains object code similar or equal to the .o files created during compilation. The dll (or shared object) is actually very similar to an executable. When you run your application, the compile time linked shared object will have to be in the search path, which on windows will typically be the application directory. Whether QLibrary can load it or not depends a bit on how you use it. You'll have to elaborate there what you want and what you are doing right now.
-
Re: Static and Dynamic Libraries
Thanks franz. That helps. I tried linking the static library but it gives me a linker error( a reference error to the library function I call), not recognizing the first function call I make to the library. Yes, I have the headers included. Also, if I comment out the library function call, the build is ok, but the exe stays the same size, which indicates to me the library is not being included.
So, I tried using the dll. I put it in my application build directory and included the headers. the build is ok, but QLibrary says it can't load the library. Dependency walker only shows a few warnings regarding Microsoft dlls.
Also, if I pick a random MS dll and put it in my application build directory, QLibrary loads it ok.
At this point, I am thinking there must be something wrong with my library (I built it from source using Mingw/msys).
-
Re: Static and Dynamic Libraries
Whatever you're building now and trying to link to the library will have to be built using the same tools the library was built with - mingw. It may have to be rebuilt to use similar flags - for example, you can't link a library built in 64-bit mode with an application built in 32-bit mode.
-
Re: Static and Dynamic Libraries
Thanks Six, I built the library on the same 32 bit Windows machine I made my Qt application on.
So, that should not be a problem, right?
-
Re: Static and Dynamic Libraries
It may not be the problem, at least if they were built with the same compiler. Post the actual error message you're getting.
-
Re: Static and Dynamic Libraries
Well, when I try to link to the static library, the error message is:
C:\CPP\QT_Projects\HRLogger_Development/lotwupload.cpp:23: undefined reference to `_imp__tqsl_init@0'
For reference, the pro file entry is:
Code:
INCLUDEPATH += C:\mingw\msys\1.0\home\wayne\tqsllib\include
LIBS += -L"C:\mingw\msys\1.0\home\wayne\tqsllib\lib" -ltqsllib
The library .h files are included in my application.
And the first library call (where it fails) is :
Code:
int ret = tqsl_init();
And this function is defined in tqsllib.h which is included in my application.
So what could I be doing wrong here?
-
Re: Static and Dynamic Libraries
Hi ,
Open the Makefile of ur project, see LIBS + line
if double quotes is missing in pro file,
Try LIBS += -L$$quote("C:\mingw\msys\1.0\home\wayne\tqsllib\lib ")
or
may be u can try by adding the library's path in the PATH variable. u can also try path in QtCreator's projects->Run Settings
Try run qmake , clean & compile the project entirely
hope it helps
Thnks
Bala
-
Re: Static and Dynamic Libraries
Forward slashes. If possible, always use forward slashes.
-
Re: Static and Dynamic Libraries
Thanks folks, tried that stuff, no luck. Same problem.
If I comment out the call to the library function, and do a build, both with and without the LIBS lines in the pro file, the size of the application exe does not change.
Does anyone else think this is an indicator that the library is not included in the exe? And that would cause the linker error when the library function call is left in?
-
Re: Static and Dynamic Libraries
For whatever reason, the linker is not able to locate the library you're trying to link to. It may be a quoting or backslash issue, as others have suggested, or simply a case of the library not where you're telling the linker to look for it. Check your path, make sure the library is really there and that the path it's on matches the one in your project file.
-
Re: Static and Dynamic Libraries
Ok, I checked all of that and it is ok.
Here is where part of my newbie confusion comes in. The doc for building the tqsllib says to use the configure command with --disable-shared, which I did. Then it says after running "make install" "This should result in the creation of the tqsllib2.dll" Which it did.
Wouldn't using --disable-shared mean that you are creating a static library? Like a lib.a file? If so, then why does it create a dll?
It also creates the files libtqsllib.a libtqsllib.la and tqsllibd.a in the lib directory where I built it. tqsllib2.dll is in the bin directory.
I have been trying to use the tqsllib.a file as a static library. Is this incorrect?
Can someone explain this to me? I am really library confused.
At least I was able to build the qserialdevice static library and include it in my application and it is working fine. But this library is just not the same.
-
Re: Static and Dynamic Libraries
Looks like your answer lies here:
Code:
#if defined(__WIN32__) && !defined(TQSL_NODLL)
#ifdef TQSLLIB_DEF
#define DLLEXPORT __stdcall __declspec(dllexport)
#define DLLEXPORTDATA __declspec(dllexport)
#else
#define DLLEXPORT __stdcall __declspec(dllimport)
#define DLLEXPORTDATA __declspec(dllimport)
#endif
#else
#define DLLEXPORT
#define DLLEXPORTDATA
#endif
You aren't defining any of these symbols yourself are you?
Quote:
C:\CPP\QT_Projects\HRLogger_Development/lotwupload.cpp:23: undefined reference to `_imp__tqsl_init@0
Here, the linker expects to find a function with the stdcall convention. It seems that you build the library one way, and you are trying to link against it in other.
Examine your defines for building it, and check your defines for linkage.
-
Re: Static and Dynamic Libraries
Thanks Timoteo. I can see that you are trying to tell me something important, but being a C++ newbie, I am having a hard time understanding it.
Here are my questions/comments:
1. When I compile the tqsl library and the files tqsllib.a and tqsllib2.dll are created - isn't the tqsllib.a the static and the tqsllib2.dll the dynamic?
2. If the configure is run with --disable-shared, why does it create the dll?
3. You said "It seems that you build the library one way, and you are trying to link against it in other." I am just trying to link against the static tqsllib.a I thought that was what I had in my pro file. So what do you mean?
4. I don't think I am defining any symbols. I am just calling the first function I need in the library that is tqsl_init();
5. Why does one need the code you posted?
6. What do you mean by "Examine your defines for building it, and check your defines for linkage"?
Sorry for all of the newbie questions to your post, I know you are trying to help.
I am really trying to get this - I have 5 C++ books and 5 Qt books, but none of them really explain how to work with external libraries.
If I could find a good reference that explains all of this I wouldn't have to waste all of your time with dumb questions.
-
Re: Static and Dynamic Libraries
The code I posted is from the header of the library in question. It uses a set of defined symbols to determine whether you are importing or exporting symbols. It also determines the calling convention that the linker should expect (__cdecl for static lib, and __stdcall for dynamic lib). From another quick glance it appears that you need to define TQSL_NODLL in order to link statically.
your .pro
Code:
DEFINES += TQSL_NODLL
It also appears that you need to define TQSL_NODLL (not in source, but passed to the compiler) when building the library to achieve static linkage.
-
Re: Static and Dynamic Libraries
Thanks Timoteo, that helps.
The code in the library is
Code:
/** Initialize the tQSL library
*
* This function should be called prior to calling any other library functions.
*/
DLLEXPORT int tqsl_init();
I have included the tqsllib.h in my application, and I call the init function like this
Code:
int ret = tqsl_init();
And the build error is:
C:\CPP\QT_Projects\HRLogger_Development/lotwupload.cpp:19: undefined reference to `tqsl_init'
So what am I missing now?
-
Re: Static and Dynamic Libraries
Did you rebuild the library as static? Could you upload your project somewhere and send it to me via PM or attach it here?
Added after 5 minutes:
Just some text to augment the replies to your previous questions:
It is important to understand just what a function declaration is. I am going to supply one and break it down while taking the win32 platform as an example.
Code:
int __stdcall doSomethingAwesome(int coolArg);
Moving from left to right, we start with the return type. Now everyone knows what this is, but why does the compiler actually need it? The return type in this example tells the complier that the EAX register
will have a signed integer value in it when the procedure returns. In other words, the return type specifies the post-condition of the EAX register. Most know that compilers can much more easily inline
a function that returns nothing (void), and now you may know why. That's because the compiler knows that you have no dependency on the post-condition of EAX and it now has an extra register to use
when inlining.
Next is the calling convention. The calling convention tells the compiler how the parameters must be passed into the procedure and who is responsible for balancing the stack upon procedure return (caller versus callee). For instance, on win32 the parameters are pushed onto the stack, in win64 the parameters are passed in registers.
Next is the function identifier. Pretty much self-explanatory. Just note that this can be decorated or undecorated (extern "C").
Finally, we have the parameter. The most important thing that the compiler has to know about the parameter is the SIZE of the type. The compiler cannot generate correct procedure prologue without knowing this. In other words, the compiler cannot deduce the proper pre-conditions for entry into the procedure and cannot setup a correct stack frame for it. The same applies to procedure epilogue generation.
Most of this stuff is handled transparently by the compiler and you'd never have to know the compiler's reasons. When you get into mixed language projects, though, it comes in handy to know this stuff.
How this applies to your problem: The calling convention must be specified the same way when building the library and when linking to it.
-
Re: Static and Dynamic Libraries
I definitely still have a lot to learn about C++, :) That's what you get with an old hardware engineer!
I created a small test project but the files were too big to attach and I couldn't see a way to send an attachment on a PM so I put them on my website. Go to k4elo.net and the Download page. 3 files - the test project, the tqsl compiled library, and the config log from the library compile.
And thanks again for all of your help.
-
Re: Static and Dynamic Libraries
I had a look at the lib requirements and saw that you need the Windows DDK (WDK) in order to build it. I've been busy so I've not had the chance to setup my environment here at home for a build. When I establish a baseline that will build and link properly, I will post the results back to you (unless you beat me to it).
-
Re: Static and Dynamic Libraries
Many thanks Timoteo I really appreciate all of your efforts, you are a hero.
By sheer luck and a great deal of perspiration and trial and error, I have gotten the dll to load into my application in a test project test_lib2.
All I did was to put the includepath in the pro file, include the library header, then put the tqsllib2.dll into the debug directory and used QLibrary to load the library.
qDebug reports the library is loaded.
Now I am working on getting the tqsl_init() function resolved. No success yet.
I don't know if I am on the right path or not, but it looks promising.
I'll report back later tonight or tomorrow morning with my results.
I am still confused about library building. That is the library.a vs the library.dll when you build a library with --disable-shared.
I thought that would create a library.a that you could link statically. Appears not to be the case as I had no luck with linking tqsllib.a statically.
Just shows you how much I don't know about C++ yet.
Hoping that someone puts an entry into the wiki explaining external library usage.
-
Re: Static and Dynamic Libraries
This library definitely is different (in the bad way). For example, I cannot get it to build cleanly on Linux due to it being bound to an older OpenSSL (if I hack around on it, I can get it to build, but it is nasty). Btw, what I said about it requiring the Windows DDK - total brain spasm. Dunno where that came from really. Also the configuration for the library appears to be totally borked on Windows (VS compiler).
The Trusted QSL software does come with a prebuilt library with it, but
Code:
dumpbin /exports tqsllib2.dll
causes the linker to crash so I cannot even inspect the symbols that it exports.
-
Re: Static and Dynamic Libraries
None of that surprises me. Wysota said something in an earlier post that indicated it wasn't too great.
I exchanged emails with the author and he said he really only provided the pre-built dll for Windows developers using Visual Basic and I know there are several Windows programs out there that are successfully using that approach.
When I built the library on Windows using Mingw, I used the current versions of openssl, expat, and zlib and it built ok.
I have gotten the tqsl_init() function to return success as follows:
Code:
tqsllib2.setFileName("c:/cpp/qt_projects/lib_test2/debug/tqsllib2.dll");
tqsllib2.load();
qDebug() << "is tqsllib2 loaded ? " << tqsllib2.isLoaded();
qDebug() << "lib load error is " << tqsllib2.errorString();
int ret;
typedef int (*MyPrototype) ();
MyPrototype tqsl_init = (MyPrototype) tqsllib2.resolve("tqsl_init");
if (tqsl_init)
{
ret = tqsl_init();
}
qDebug() << "ret is now " << ret;
Now I am working on getting the tqsl_getStationLocation function to work.
However, I want to be able to offer my application on Linux and Mac as well as Windows and if I'm not going to be able to compile the library for the other O/S and won't be able to use the library I built on Windows, then I think I am going to give up on adding the features to my application that the library offers.
Am I correct in assuming I won't be able to use the dll I built under Windows to create versions of my application for Linux and Mac? If that is the case, then I'm giving up on it unless they re-write the library.
Thanks again for all of your help, you have gone above and beyond what one would expect on the forum and I truly appreciate it. I'm sorry it turned out to be a waste of your time.
-
Re: Static and Dynamic Libraries
Waynew,
I have been following your travails with tsqllib. Not being a windows guy, I can't help you with your dll problem but I wanted to let you know that the Debian repositories have a package (tqsllib-dev) that is being maintained with the most recent patches being about a year old. One of the patches addresses the problem that Timoteo had:
Code:
-#elif (OPENSSL_VERSION_NUMBER & 0xfffff000) ==0x00907000
+#elif ((OPENSSL_VERSION_NUMBER & 0xfffff000) == 0x00907000 || (OPENSSL_VERSION_NUMBER & 0xfffff000) == 0x00908000)
I compiled the lib from source and ran your test program successfully.
Norm
-
Re: Static and Dynamic Libraries
Gaw, just my luck. Well, I'm a fairly stubborn guy so I would have probably ignored the package anyway, but that is great to know.
-
Re: Static and Dynamic Libraries
Well, I am a little confused now, not being a C++ or Linux expert. My native language is Oracle pl/sql, not too complicated, but it earns a living :)
Thanks for your report Norm, I appreciate it, but I'm not sure what you mean that you ran my test program successfully.
And where did you ever find that Debian info?
Only being a little experienced with Linux, I don't guess that package would do me any good on say, Ubuntu? Or other distributions?
One last (I think) question guys - I don't suppose the dll I built with Mingw on Windows is going to do me any good if I want to compile for Linux or Mac?
Maybe someone can talk Jon Bloom/ARRL into re-writing this thing so it is up to date. He is linking to old openssl and zlib versions that have known security risks from what I can see.
Thanks for all of your help guys, I really appreciate it.
Wayne
Amateur Radio Operator K4ELO
Just trying to make a good logging program for Windows/Linux/Mac that supports tqsl but it's looking impossible.
-
Re: Static and Dynamic Libraries
Quote:
Originally Posted by
waynew
.... but I'm not sure what you mean that you ran my test program successfully.
I compiled the Lib_Test app from your website against the tqsllib on my machine and got the following output:
Quote:
And where did you ever find that Debian info?
I usually check out the Debian repositories first. The number of libs and apps in there is amazing. Ubuntu is a Debian derivative so AFAIK you can use Debian packages on Ubuntu but a tqsllib package is available in Ubuntu Universe too: here
Quote:
... I don't suppose the dll I built with Mingw on Windows is going to do me any good if I want to compile for Linux or Mac?
You'll have to build a Linux, Mac and Windows version of the lib.
Norm
-
Re: Static and Dynamic Libraries
Yes, I get the same results with the package here on Ubuntu 10.10 and Mint. Clean build with
-
Re: Static and Dynamic Libraries
Thanks guys, this is making more sense to me now.
Then does that mean I am going to have to do something like this for every library function call?
Code:
int loc;
tQSL_Location location;
location = "K4ELO";
char *myLoc = locName.toUtf8().data();
typedef int (*MyPrototype2)(*loc, *name);
MyPrototype2 tqsl_getStationLocation = (MyPrototype2) tqsllib2.resolve("tqsl_getStationLocation");
loc = tqsl_getStationLocation(&location, myLoc);
qDebug() << "loc returns " << loc;
Which won't compile due to my lack of basic C++ skills.
But if you can tell me what is wrong with it, I would appreciate it.
-
Re: Static and Dynamic Libraries
Code:
/*error here because your parameters are missing type*/
typedef int (*MyPrototype2)(*loc, *name);
/*perhaps something like this is what you meant?*/
int (*MyPrototype2)(char*, char*);
I would put all of your function pointers into a namespace and initialize with a free function when your application starts. The will help your symbol management.
Code:
namespace tqsl
{
int (*getStationLocation)(char*,char*) = 0;
}
Has the benefit of being able to say
Code:
tqsl::getStationLocation("?", "?");
which looks alot better than the C convention of
Code:
tqsl_getStationLocation
and it keeps your global namespace from being polluted.
-
Re: Static and Dynamic Libraries
OK, I understand the namespace part and how they work, and that's an excellent suggestion, but what do you mean by a free function to initialize?
Then what does the resolve syntax look like when using the namespace? I have tried a few different things after adding the namespace, but they won't compile, so I'm not getting it right. Guess I don't understand how that changes the syntax other than the tqsl::
Do I still have to do this cumbersome MyPrototype stuff?
It really is hard to teach an old dog new tricks. When I was in college, all they taught was Fortran on an IBM 1620. For all of my frustration, I do really like C++, it is very elegant and powerful. If I live long enough, maybe I will get proficient. At least the rest of my application functions well, although you guys would probably throw up at my code, but the beta testers report no current bugs.