You are not logged in.

mascix

Beginner

  • "mascix" started this thread

Posts: 11

Location: istanbul

Occupation: software engineer

  • Send private message

1

Monday, January 19th 2004, 1:00am

how to make shared objects with QT (creating .so files in linux or .dll in win32)

how to make shared objects with QT (creating .so files in linux or .dll in win32)
INTRODUCTION
-----------
if u want to have smaller executable and dont want to see all codes togather u can use .so files. and if u want to have a moduler application that changes modules by modules not totally. and if u want to have same ability in another applications u should use .so.
for example: u r developing gaim. u know gaim supports a lot of protocol ICQ/MSN/... anyway. when user dont use msn protocol it shouldnt be loaded. with this way memory will be used as small as possible.
another example: u want to develop a MSN client application. if gaim developers made that msn protocol as GPL I mean open source. and publish that libgaimmsn.so. u can use that .so and dont lose time for making a msn protocol implementation.

I hope u understood what r loadable shared libraries/objects using for.

IMPLEMENTATION
--------------
First qmake is a good tool that make life better and easier :) and read QT documentation.
it is so easy to make lib***.so files with it. I havent tried it before in linux or win32 (as DLL). then I made qt_lib_try.pro file for qmake. before go on u should check that u have QTDIR enviroment exported and in PATH QTDIR/bin included.

///qt_lib_try.pro
TEMPLATE = lib
INCLUDEPATH += .
LIBS+= -lqui #this line needed by QWidgetFactory
# Input
HEADERS += myclass.h
SOURCES += myclass.cpp
CONFIG += warn_on

as u see there are 2 files will make one shared object(.so).

I want something really dynamic :) and flexible. and decided to use QWidgetFactory and have a form from .ui file ;) if I do that I compile one time my .so file and example application which is using my .so and change everything just playing with .ui file in designer :)

///myclass.h
#include <qwidget.h>
#include <qwidgetfactory.h>
#include <qhostaddress.h>
#include <qsocket.h>

class MyClass
{
public:
int x;
QWidget *w;
MyClass() {
w=QWidgetFactory::create("form1.ui");
x=50;
w->show();
};

void repair(){
qDebug("haha");
};
};
///the exported function
extern "C"
{
MyClass* GetClass();
}

///myclass.cpp
#include "myclass.h"

MyClass* GetClass()
{
MyClass* cl= new MyClass();
return cl;
}

that two files will make .so file and thats job will be just open a form from constructor with .ui :)

we have .pro and .h and .cpp file now making lib from them for using in our example app.

qmake -o Makefile qt_lib_try.pro
make

[mascix@linmascix qt_lib_try]$ make
g++ -c -pipe -Wall -W -O2 -fomit-frame-pointer -pipe -march=i586 -mcpu=pentiumpro -fPIC -DQT_NO_DEBUG -I$QTDIR//mkspecs/default -I. -I. -I$QTDIR//include -o myclass.o myclass.cpp
rm -f libqt_lib_try.so.1.0.0 libqt_lib_try.so libqt_lib_try.so.1 libqt_lib_try.so.1.0
g++ -shared -Wl,-soname,libqt_lib_try.so.1 -o libqt_lib_try.so.1.0.0 myclass.o -L$QTDIR//lib -lqt-mt -lqui
ln -s libqt_lib_try.so.1.0.0 libqt_lib_try.so
ln -s libqt_lib_try.so.1.0.0 libqt_lib_try.so.1
ln -s libqt_lib_try.so.1.0.0 libqt_lib_try.so.1.0

as u see our shared objects ready to use. now we need an example application for using these files.

////example.cpp
#include <qapplication.h>
#include <qlibrary.h>
#include "myclass.h"

int main( int argc, char **argv )
{
QApplication a(argc,argv);
typedef MyClass* (*pf)();
pf function=(pf)QLibrary::resolve(("./libqt_lib_try.so"),"GetClass");
MyClass* cl= function();
cl->repair();
qDebug("here is our x from shared object x=%d",cl->x);
a.setMainWidget(cl->w);
return a.exec();
}

here how should we compile that example:
gcc example.cpp -I $QTDIR/include/ -lqt-mt -L $QTDIR/lib/ -L ./libqt_lib_try.so -o example

./example
haha
here is our x from shared object x=50

tataa everything ok and our application working. but u need one more thing if u r a lazy person :)

//form1.ui
<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
<class>Form1</class>
<widget class="QWidget">
<property name="name">
<cstring>Form1</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>231</width>
<height>154</height>
</rect>
</property>
<property name="caption">
<string>Form1</string>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="geometry">
<rect>
<x>30</x>
<y>30</y>
<width>112</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>Mascix made me</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>pushButton1</cstring>
</property>
<property name="geometry">
<rect>
<x>80</x>
<y>100</y>
<width>110</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>Exit</string>
</property>
</widget>
<widget class="QLCDNumber">
<property name="name">
<cstring>lCDNumber1</cstring>
</property>
<property name="geometry">
<rect>
<x>30</x>
<y>60</y>
<width>64</width>
<height>23</height>
</rect>
</property>
</widget>
</widget>
<connections>
<connection>
<sender>pushButton1</sender>
<signal>clicked()</signal>
<receiver>Form1</receiver>
<slot>close()</slot>
</connection>
</connections>
<layoutdefaults spacing="6" margin="11"/>
</UI>

This post has been edited 1 times, last edit by "mascix" (Oct 17th 2005, 7:54pm)


e8johan

Professional

Posts: 1,195

Location: Sweden

  • Send private message

2

Monday, January 19th 2004, 5:47am

Great intro to the subject! A few hints though: put all code in a tar.gz archive and attach it then put the code in the article within code-tags.

hufeifei

Beginner

Posts: 2

Location: china

  • Send private message

3

Saturday, February 21st 2004, 8:13am

didn't work!

E:\RisWave_Test\myclass>E:

E:\RisWave_Test\myclass>qmake -o Makefile qt_lib_try.pro

E:\RisWave_Test\myclass>nmake

Microsoft (R) Program Maintenance Utility Version 6.00.8168.0
Copyright (C) Microsoft Corp 1988-1998. All rights reserved.

link /NOLOGO /DEBUG /SUBSYSTEM:windows /DLL /LIBPATH:"C:\Qt\3.2.2\lib" /
OUT:myclass.dll @C:\DOCUME~1\hujf\LOCALS~1\Temp\nmb01836.
Creating library myclass.lib and object myclass.exp
myclass.obj : error LNK2001: unresolved external symbol "public: static class QC
har QChar::null" (?null@QChar@@2V1@A)
myclass.obj : error LNK2001: unresolved external symbol "private: static struct
QStringData * QString::shared_null" (?shared_null@QString@@0PAUQStringData@@A)
myclass.obj : error LNK2001: unresolved external symbol "public: static class QS
tring QString::null" (?null@QString@@2V1@A)
myclass.obj : error LNK2001: unresolved external symbol "private: static struct
HPALETTE__ * QColor::hpal" (?hpal@QColor@@0PAUHPALETTE__@@A)
myclass.obj : error LNK2001: unresolved external symbol "private: static enum QC
olor::ColorModel QColor::colormodel" (?colormodel@QColor@@0W4ColorModel@1@A)
myclass.obj : error LNK2001: unresolved external symbol "private: static class Q
WidgetMapper * QWidget::mapper" (?mapper@QWidget@@0PAVQWidgetMapper@@A)
myclass.obj : error LNK2001: unresolved external symbol "public: static class QW
idget * __cdecl QWidgetFactory::create(class QString const &,class QObject *,cla
ss QWidget *,char const *)" (?create@QWidgetFactory@@SAPAVQWidget@@ABVQString@@P
AVQObject@@PAV2@PBD@Z)
myclass.dll : fatal error LNK1120: 7 unresolved externals
NMAKE : fatal error U1077: 'link' : return code '0x460'
Stop.

E:\RisWave_Test\myclass>pause
÷ û.çí . . .
ask for QT program

alshurik

Beginner

Posts: 1

Location: Russian Federation

Occupation: programmer

  • Send private message

4

Saturday, April 10th 2004, 4:14am

try:

//myclass.cpp
.....
#ifdef WIN32
extern "C" __declspec( dllexport )
#else
extern "C"
#endif
{
MyClass* getClass()
}
....

it works under Visual C++.
the end is somewhere in the code

rshadow

Beginner

Posts: 34

Location: South Korea

Occupation: DOD

  • Send private message

5

Monday, July 26th 2004, 1:19pm

RE: how to make shared objects with QT (creating .so files in linux or .dll in win32)

Has anybody compiled this under windows with any success? I have never created a dll / library before in my projects and would like to give it a try, but have had no luck.. below is the code I'm trying

// myclass.h

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <qwidget.h>
#include <qlabel.h>


class MyClass
{
  public:
     MyClass();
     int x;
     QWidget *w;
     QLabel *l;
};

// The exported function
extern "C"
{
 MyClass* GetClass();
}


// myclass.cpp

Source code

1
2
3
4
5
6
7
8
9
10
11
12
#include "myclass.h"

#ifdef WIN32
extern "C" __declspec( dllexport )
#else
extern "C"
#endif
MyClass* GetClass()
{
 MyClass* cl = new MyClass();
 return cl;
}


// testdll.pro

Source code

1
2
3
4
5
6
7
8
TEMPLATE = lib
INCLUDEPATH += .
LIBS += -lqui

# Input
HEADERS += myclass.h
SOURCES += myclass.cpp
CONFIG += warn_on dll plugin


// test.pro

Source code

1
2
3
4
5
6
7
8
9
10
######################################################################
# Automatically generated by qmake (1.06c) Mon Jul 26 05:43:33 2004
######################################################################

TEMPLATE = app
INCLUDEPATH += .

# Input
HEADERS += myclass.h
SOURCES += main.cpp


// main.cpp

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <qapplication.h>
#include <qlibrary.h>
#include <qlabel.h>
#include "myclass.h"

int main( int argc, char *argv[])
{
  QApplication a(argc, argv);
  typedef MyClass* (*pf)();
  pf function=(pf)QLibrary::resolve(("testdll.dll"), "GetClass");
  MyClass *cl = function();
  QLabel *label = new QLabel("test label", 0);

  a.setMainWidget(label);
  label->show();

  //a.setMainWidget(cl->l);
  return a.exec();
}


The application compiles ok.. however when executed the program GPFs . Any ideas? Perhaps I'm going about this wrong.

Update:
I tried playing around with stuff and added the dll to the Makefile which resulted in the following output.. if it helps

Source code

1
2
3
4
5
6
7
8
9
10
11
12
C:\dlltext\test>make
MAKE Version 5.2  Copyright (c) 1987, 2000 Borland
        bcc32 -c -tWR -w -w-hid -tWM -O2 -x- -RT- -DUNICODE -DQT_DLL -DQT_THREAD
_SUPPORT -DQT_NO_DEBUG -I"." -I"C:\Qt\329350~1.1NO\include" -I"C:\dlltext\test"
-I"C:\Qt\329350~1.1NO\mkspecs\win32-borland" -omain.obj main.cpp
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
main.cpp:
        ilink32 @MAKE0000.@@@
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: 'C:\DLLTEXT\TEST\TESTDLL.DLL' contains invalid OMF record, type 0x4d

** error 2 ** deleting test.exe
Linux / Win32 Developer
Gentoo Linux User

This post has been edited 1 times, last edit by "rshadow" (Jul 26th 2004, 1:33pm)


Posts: 16

Location: France

Occupation: R&D director, software engineer

  • Send private message

6

Monday, July 26th 2004, 4:14pm

here is the code for MyClass

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// -*- C++ -*-
#ifndef MYCLASS
#define MYCLASS

#include "common.h"
#include <qwidget.h>
#include <qlabel.h>

class MCEXP MyClass {
public:
  MyClass();
  int x;
  QWidget *w;
  QLabel *l;
} ;

#endif


The source of myclass:

Source code

1
2
3
4
#include "myclass.h"

MyClass::MyClass() {
}

The common.h file defines the exports for Windows.
If you have several classes to export into the dll, include the common.h file for each class (supposing one class definition per .h file). This file defines the MCEXP which is a dllexport or dllimport (if MYCLASS_EXP is defined in your makefile). Take a look at the MyClass deinition, you will see the MCEXP keyword before the class name. This will export the entire class in the dll

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef MYCLASS_COMMON
#define MYCLASS_COMMON

#if defined(_WIN32) || defined(WIN32)
#ifdef MYCLASS_EXP
#define MCEXP __declspec(dllexport)
#else
#define MCEXP __declspec(dllimport)
#endif
#else
#define MCEXP
#endif
#endif


The .pro file to create the DLL is (Note that we define MYCLASS_EXP => the class is exported (see common.h))

Source code

1
2
3
4
5
6
7
8
TEMPLATE      = lib
TARGET        = myclass
CONFIG	     += warn_off release dll
win32 {
  DEFINES  += MYCLASS_EXP
}
HEADERS += myclass.h
SOURCES += myclass.cxx



Now for the test example:
The main.cxx file:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <qapplication.h>
#include <qlabel.h>
#include "myclass.h"

int main( int argc, char *argv[]) {
  QApplication a(argc, argv) ;
  MyClass *cl = new MyClass() ;
  QLabel *label = new QLabel("test label", 0) ;

  a.setMainWidget(label);
  label->show();

  return a.exec();
}


...and the corresponding .pro file to compile the binary and link with your lib (dynamically). Note that the MYCLASS_EXP is not defined => use dllimport.

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
TEMPLATE = app
TARGET   = test
INCLUDEPATH += .

# Input
SOURCES += main.cxx

win32 {
  LIBS += myclass.lib
}

unix {
  LIBS += -lmyclass
}

br06

Trainee

Posts: 121

Location: Germany

Occupation: surveying engineer

  • Send private message

7

Monday, July 26th 2004, 9:39pm

RE: how to make shared objects with QT (creating .so files in linux or .dll in win32)

Hi rshadow,

can you plz attach a zip-file of the sources.

hi Frantz,

you bind the DLL to your app at compile time. At run time the app knows all symbols of the dll.
Rshadow will bind the DLL at run time.

Christian

rshadow

Beginner

Posts: 34

Location: South Korea

Occupation: DOD

  • Send private message

8

Tuesday, July 27th 2004, 12:43am

RE: how to make shared objects with QT (creating .so files in linux or .dll in win32)

br06,

Yes, I am trying to bind at runtime. I have attached a zip of my sources.

Frantz,
Thank you however. You code is still extremely helpfull. Not to get on another topic, but how would one bind at compile time on linux? Update: sorry I read your post again and it appears that its setup for both win32 and linux.
rshadow has attached the following file:
  • dlltext.zip (20.45 kB - 350 times downloaded - latest: Today, 9:16am)
Linux / Win32 Developer
Gentoo Linux User

This post has been edited 1 times, last edit by "rshadow" (Jul 27th 2004, 12:47am)


br06

Trainee

Posts: 121

Location: Germany

Occupation: surveying engineer

  • Send private message

9

Tuesday, July 27th 2004, 12:15pm

RE: how to make shared objects with QT (creating .so files in linux or .dll in win32)

Hi,

the declaration of the exported function GetClass should be

Source code

1
extern "C" _declspec(dllexport) MyClass *GetClass();


Another problem is that you want to use a member variable. As far as i know its only possible to access class members which are virtual.

Christian

br06

Trainee

Posts: 121

Location: Germany

Occupation: surveying engineer

  • Send private message

10

Tuesday, July 27th 2004, 7:48pm

RE: how to make shared objects with QT (creating .so files in linux or .dll in win32)

Hi,

i've created a small test DLL and application which runs under windows. Perhaps someone can change this for running on linux.

The idea to this test i found at
http://www.codeguru.com/Cpp/W-P/dll/impo…rticle.php/c123

Hope this will help to understand the subject.

Christian
br06 has attached the following file:
  • DLLTest.zip (1.56 kB - 375 times downloaded - latest: Yesterday, 5:41am)

This post has been edited 1 times, last edit by "br06" (Jul 27th 2004, 7:50pm)


rshadow

Beginner

Posts: 34

Location: South Korea

Occupation: DOD

  • Send private message

11

Wednesday, July 28th 2004, 11:37am

RE: how to make shared objects with QT (creating .so files in linux or .dll in win32)

I will investigate further, but I could not get this to run either. this code also produces a serious of GPF's on my system.

However, basicly, there is no "Qt" cross platform way of bulding shared libraries that can bind at run time?

Also, I'm an expert or nothing, but I don't see why the following code wouldn't release a class in a dll theoreticly anyways.

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MyClass
{
  public:
   MyClass();
   MyClass* getclass();
}

MyClass:MyClass()
{
}

MyClass* getclass()
{
   MyClass* cl = new MyClass();
   return cl;
}


Assuming the function getclass is properly exported to a DLL or .so
Linux / Win32 Developer
Gentoo Linux User

br06

Trainee

Posts: 121

Location: Germany

Occupation: surveying engineer

  • Send private message

12

Wednesday, July 28th 2004, 12:57pm

RE: how to make shared objects with QT (creating .so files in linux or .dll in win32)

Hi rshadow,

Quoted

I will investigate further, but I could not get this to run either. this code also produces a serious of GPF's on my system.


Do you mean the example which i've attached in my last post? I 've compiled with VC.net, QT 3.2.1 and tested under XP.
You can check the return values to find out, where you get a NULL pointer.

Quoted

However, basicly, there is no "Qt" cross platform way of bulding shared libraries that can bind at run time?


Why not? QLibrary encapsulates the system specific part. You can hide _declspec(dllexport) by a macro. The rest is C or C++ specific.

Christian

rshadow

Beginner

Posts: 34

Location: South Korea

Occupation: DOD

  • Send private message

13

Tuesday, August 3rd 2004, 11:20am

RE: how to make shared objects with QT (creating .so files in linux or .dll in win32)

Hmmm.. maybe I'm just doing something wrong. I have tried this (your sample app) both on windows me, windows server 2003 and Linux (2.6). All versions of windows I get a app GPF, and linux gives me a seg fault. The app will compile but dies at runtime. The only modifications I did was removed test.h from the test.pro project file (because test.h is not used and isn't present) and when compiling on linux I changed the extern commands to extern "C".

I never thought a shared library would be so hard to build. I just don't get it. Almost every app that comes out now is plugin capable. This is starting to raise my blood pressure.

Any other suggestions?
Linux / Win32 Developer
Gentoo Linux User

br06

Trainee

Posts: 121

Location: Germany

Occupation: surveying engineer

  • Send private message

14

Tuesday, August 3rd 2004, 6:53pm

RE: how to make shared objects with QT (creating .so files in linux or .dll in win32)

Hi,

i'm confused. On my XP and on a 2000 the example runs. You get the GPF, when you have invalid pointers. So i think the library won't be loaded. In my example i didn't check the return values. In the attacched file i changed the sample for this reason. Hope this helps you to find the mistake. If not, i don't have another idea.

Perhaps someone else on the forum can test the example.

Quoted

I never thought a shared library would be so hard to build. I just don't get it. Almost every app that comes out now is plugin capable. This is starting to raise my blood pressure.


Don't give up. On my real progam, i have also a little bit of trouble.
But it's nice, if you get a toolbar and a submenu from the dll after solving the probs. :D

Christian
br06 has attached the following file:
  • main.cpp (1.48 kB - 280 times downloaded - latest: Jul 25th 2010, 3:24am)

This post has been edited 1 times, last edit by "br06" (Aug 3rd 2004, 6:55pm)


rshadow

Beginner

Posts: 34

Location: South Korea

Occupation: DOD

  • Send private message

15

Wednesday, August 4th 2004, 3:07am

RE: how to make shared objects with QT (creating .so files in linux or .dll in win32)

They errors I get on all platforms are

"The symbol "CreateTest" could not be resolved" .. not sure why.. however I do have one idea.. I've used both gcc and borland compilers.. let me pull out MSVC and see if the M$ compiler makes a difference.
Linux / Win32 Developer
Gentoo Linux User

rshadow

Beginner

Posts: 34

Location: South Korea

Occupation: DOD

  • Send private message

16

Wednesday, August 4th 2004, 10:50am

RE: how to make shared objects with QT (creating .so files in linux or .dll in win32)

Ok, as an update when this app is compiled under M$ compiler it works. Any ideas why this does not work under gcc or borland? Although I can get it to work under msvc this is hardly an option as it makes the application limited to users with msvc. Linux and borland users are out of luck. There has to be a better solution.

Why I really don't understand is why this work with msvc and nothing else.
Linux / Win32 Developer
Gentoo Linux User

Posts: 2,162

Location: Graz, Austria

Occupation: Student

  • Send private message

17

Thursday, August 5th 2004, 11:41am

Can you try Q_EXPORT instead of extern "C" __declspec(dllexport)?

Cheers,
_
Qt/KDE Developer
Debian User

rshadow

Beginner

Posts: 34

Location: South Korea

Occupation: DOD

  • Send private message

18

Thursday, August 5th 2004, 11:44am

I get the same results with Q_EXPORT :-(
Linux / Win32 Developer
Gentoo Linux User

hatulflezet

Professional

Posts: 1,301

Location: Munich Germany

Occupation: Programmer

  • Send private message

19

Friday, August 6th 2004, 3:06pm

attached is a "tamplate" pro file for libs I use under linux.
Fill in the right information (sources and libs) for your projects and try it.
hatulflezet has attached the following file:
Click here! I dare ya'!! :]
Project Archimedes
----------------------------------------------------------
"Don't panic, and thanks for all the fish!"

This post has been edited 3 times, last edit by "hatulflezet" (Aug 6th 2004, 3:24pm)


kandalf

Intermediate

Posts: 276

Location: Argentina

Occupation: Developer

  • Send private message

20

Thursday, August 12th 2004, 3:13pm

RE: how to make shared objects with QT (creating .so files in linux or .dll in win32)

Quoted

They errors I get on all platforms are "The symbol "CreateTest" could not be resolved" .. not sure why..


Well, I haven't tried this example in particular, but I had a similar error, but just in window$, the fact is that the exported symbol wasn´t exported with the same name tha it was in the code but with the name precceded by an underscore. For example, in a code such as:

Source code

1
2
3
4
5
6
7
extern "C"
{ 
               void __declspec(dllexport) myFunction(){
                         do something 
               } 

}


The exported symbol was:

Quoted

_myFunction


I realized of this by the impdef.exe utility that comes with borland command line free tools wich extracts the exported symbols from a dll.

Hope it help.
Kandalf
There's no place like ~

This post has been edited 2 times, last edit by "kandalf" (Aug 12th 2004, 3:14pm)


Rate this thread