PDA

View Full Version : Custom widget - Only works in Designer



Darhuuk
7th January 2008, 16:38
Hi, I've been tying to fix this bug for over 6 hours now and finally decided to make an account here. Ok, so the problem:

I made a custom widget that can show information about a current poker game, there's 4 labels that can be set (see screenshot) plus the label on the box. Everything works perfect in Designer, I tested every function by debugging everything though the widget's constructor (I just recompiled the plugin, restarted Designer and saw if the output was what it should be). So far, so good, the plugin showed up in the Designed widget menu, I could add it, move, ... everything seemed fine.

The problem is that I can't seem to use it in a different project. The .ui file compiles and everything, but g++ complains about not finding any "PokerTableInfo.h" file. I searched for it and the only location it's in is in the original map, so no surprises here, it's not in the include path... In my desperation I copied the header file into the other project's directory, but then the linker gives me errors (I'm asuming this is because it can't find the implementation of the methodes declared in the PokerTableInfo.h file).

Just to see if other custom widgets had the same problem, I made a project with the analogclock widget from the Qt examples and sure enough, I get exactly the same problem (no .h file found, etc).

Has anyone got any idea how to fix this? I'm a complete C/C++ newbie (only been programming in it for around a week), but I've programmed in a bunch of languages for the past 10 years and had some pretty intense programming courses in univeristy (Java though). So if I overlooked something, go easy on me ;).

Source code's attached in the zip, feel free to abuse it. The methods should be quite straigthforward. (And yes, I know some of the implementations are horrible, but I just want to get it to work right now, fine tuning is for later.)

high_flyer
7th January 2008, 16:55
What you need when using your designer plugin in an application is the header file, and to link against it.
So the include path should be set correctly for the header, then the libs path should include the location of the plugin (which I assume is the designer plugin directory).
In addition you need to add the plugin lib to your libs to link against, thats all.

Darhuuk
7th January 2008, 19:28
Ok, thanks! I think I almost got it. I added this to my project file:


LIBS += D:\Anthony\Progs\Qt\plugins\designer\PokerTableInf oPlugin.dll
INCLUDEPATH = D:\Anthony\Progs\Qt\include\OwnFiles

But I'm still getting this error:

release/MainWindow.o:MainWindow.cpp:(.text$_ZN15Ui_myMainW indow7setupUiEP11QMainWindow
[Ui_myMainWindow::setupUI(QMainWindow*)]+0x5b0: undefined reference to 'PokerTableInfo::PokerTableInfo(QWidget*)'

(Note: I split the error for readability. It's one big line normally.)

MainWindow is a QMainWindow in the application I'm trying to compile. The Ui_myMainWindow stuff is created by qmake from my MainWindow.ui file.

So G++ finds the dll, but I'm guessing the linker for some reason doesn't. I tried copying the dll into the project's directory, but that doesn't seem to do anything.

* Edit: Thinking about it, it would be pretty stupid if my application needed a dll to run, so I just changed it to simply include the PokerInfoTable source files. Compiles perfectly now. Having the widget plugin is nice though, now I can design in Designer and then just build with the source files. But still, I'd like to know what was causing these errors, would be nice to know for the future.

high_flyer
7th January 2008, 20:21
Thinking about it, it would be pretty stupid if my application needed a dll to run
Of crouse, that is a matter of opinion, but I tend to disagree in general with that notion.

The advantage of a dll (or shared lib) is that other applications can use it too (for example, designer, but also other applications.)
So your current approach means, you will have to statically link or include your plugin in each application that wants to use it.
What if you want to give the plugin to someone else, but don't want to disclose the code?

Your problem was that you were trying to link against the dll it self, and that doesn't work.
On windows at built time you link against the *.lib file, and at runtime, against the *.dll.

Darhuuk
7th January 2008, 22:12
Yes, true. It's just that I think this specific widget won't have much use outside of the program I'm making. But I need to be able to add & remove instances of it dynamically to my MainWindow, so that's why I made it into a widget. If my widget actually did anything generally useful, I would completely agree with you though.

Thanks for the explanation, I get it now. However, I'm afraid must really suck, because I can't get it to work. When you say the "lib" file, I'm not sure what you mean. There's a .a file and then there's the .dll. I tried linking against the .a file, but that didn't quite work out. I'm getting an "Undefined reference to ..." for every public function in my PokerTableInfo.h file. How do I create this .lib file? I searched for it, but it isn't in any directory (in fact, there's only 2 .lib files in the whole Qt map).

(Yes, it's OK if you hate my stupid questions :).)

high_flyer
7th January 2008, 23:41
There's a .a file and then there's the .dll
Now I am not sure any more if MinGW creates a lib file as well, but I think it should. (so that other windows compilers will be able to links against the lib), but as I said, I am not sure any more (it has bin a while since I compiled a lib with MinGW under windows)

So I just checked a bit here: (http://www.mingw.org/MinGWiki/index.php/sample%20DLL)

Building the DLL

To build the DLL use the following commands:

g++ -c -DBUILDING_EXAMPLE_DLL example_dll.cpp

g++ -shared -o example_dll.dll example_dll.o -Wl,--out-implib,libexample_dll.a

The -DBUILDING_EXAMPLE_DLL compiler option causes the DLL's functions to be declared as "dllexport", meaning that they will be "exported" from the DLL and available to client applications. The "-shared" option tells the linker to create a DLL instead of an .exe, and the "--out-implib" linker option causes an import library to be created, which is used later on.
Note:

The import library created by the "--out-implib" linker option is required iff (==if and only if) the DLL shall be interfaced from some C/C++ compiler other than the MinGW toolchain. The MinGW toolchain is perfectly happy to directly link against the created DLL. More details can be found in the ld info files that are part of the binutils package (which is a part of the toolchain).

So if you are using MinGW, it actually link against the DLL it self, as stated here.

So my guess is that you probably have a problem with paths somewhere or the like.

EDIT: it just occured to me that you LIBS tag in the pro file was wrong:

LIBS += -LD:\Anthony\Progs\Qt\plugins\designer\ -lPokerTableInfoPlugin

Darhuuk
8th January 2008, 00:46
Wow, thanks a lot for all the trouble you went through! Good, one more thing I won't do wrong :).