Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

Qt-interest Archive, March 2007
Creating and linking a DLL with visual studio

Pages: Prev | 1 | 2 | 3 | Next

Message 1 in thread

Hi guys,

i'm having some trouble linking to a DLL I have created using Qt and
visual studio .net 2005 (but this post should apply to other versions
of msvc).

To make it short, the project I am working on has a stand alone DLL
and a main application that links this DLL.
Both the DLL and the app use Qt.

First off, I have NO problems on *nix/gcc using the same .pro project
files.

Visual studio refuses to link the main application with the dll and
complaints about some unresolved external symbols. Here is an example:

error LNK2001: unresolved external symbol "public: static struct
QMetaObject const MvdSharedData::staticMetaObject";
(?staticMetaObject@MvdSharedData@@2UQMetaObject@@B)
moc_movieeditor.obj

My DLL exports everything correctly and I can see that
MvdSharedData::staticMetaObject is actually being exported using an
object dump.

All my link errors are similar to this one
(someClass::staticMetaObject).

Adding the DLL-project moc_*.cpp files to the main application's
project in VS would solve the problem, but this is NOT a good
solution, as I should be able to link my DLL only using the headers
and the lib/dll files, not the MOC cpp files.

Any clues? Thanks guys!


PS: the DLL builds fine, I only have trouble linking it with my main
app!

--
 [ signature omitted ] 

Message 2 in thread

Hi all
We are working on qt 3.X and Oracle 10G on LINUX. I want to know if there is
a driver for oracle 10G onn qt 3.X


Regards


Adel




--
 [ signature omitted ] 

Message 3 in thread

Adel SAFI wrote:
> Hi all
> We are working on qt 3.X and Oracle 10G on LINUX. I want to know if there is
> a driver for oracle 10G onn qt 3.X


According to _the docs_ here: 
http://doc.trolltech.com/3.3/sql-driver.html#QOCI8
there is a plugin only for Oracle 8 and 9...

However, according to _the docs_ here:
http://doc.trolltech.com/4.0/sql-driver.html#supported-databases
Qt 4.x has support for Oracle 10 as well

I don't know if it is *possible* / *legal* to backport it but if the 
answer to both conditions is yes then this could be a way to achieve 
support.

--
 [ signature omitted ] 

Message 4 in thread

Hi,

> According to _the docs_ here: 
> http://doc.trolltech.com/3.3/sql-driver.html#QOCI8
> there is a plugin only for Oracle 8 and 9...

A few lines later, the documentation reads:

	If you are using Oracle 8:
	[...]
	For Oracle version 9:
	[...]
	For Oracle version 10:
	[...]

It's just that Oracle 10 had not been released at the time the Qt 3 
documentation had been written, and the documentation has not been 
updated accordingly.

So yes, it looks like the Oracle driver in Qt 3 does support Oracle 10.

--
 [ signature omitted ] 

Message 5 in thread

>
> A few lines later, the documentation reads:
>
>     If you are using Oracle 8:
>     [...]
>     For Oracle version 9:
>     [...]
>     For Oracle version 10:
>     [...]
>
> It's just that Oracle 10 had not been released at the time the Qt 3 
> documentation had been written, and the documentation has not been 
> updated accordingly.
>
> So yes, it looks like the Oracle driver in Qt 3 does support Oracle 10.
And it's there! Ooops... Sorry for mis-informing anyone! :(

--
 [ signature omitted ] 

Message 6 in thread

Fabrizio Angius wrote:
> Hi guys,
> 
> i'm having some trouble linking to a DLL I have created using Qt and
> visual studio .net 2005 (but this post should apply to other versions
> of msvc).
> 
> To make it short, the project I am working on has a stand alone DLL
> and a main application that links this DLL.
> Both the DLL and the app use Qt.
> 
> First off, I have NO problems on *nix/gcc using the same .pro project
> files.
> 
> Visual studio refuses to link the main application with the dll and
> complaints about some unresolved external symbols. Here is an example:
> 
> error LNK2001: unresolved external symbol "public: static struct
> QMetaObject const MvdSharedData::staticMetaObject";
> (?staticMetaObject@MvdSharedData@@2UQMetaObject@@B)
> moc_movieeditor.obj
> 
> My DLL exports everything correctly and I can see that
> MvdSharedData::staticMetaObject is actually being exported using an
> object dump.
> 
> All my link errors are similar to this one
> (someClass::staticMetaObject).
> 
> Adding the DLL-project moc_*.cpp files to the main application's
> project in VS would solve the problem, but this is NOT a good
> solution, as I should be able to link my DLL only using the headers
> and the lib/dll files, not the MOC cpp files.
> 
> Any clues? Thanks guys!
> 
> 
> PS: the DLL builds fine, I only have trouble linking it with my main
> app!
I do not think you LINK a dll! You load it at run time using the QLibrary.

--
 [ signature omitted ] 

Message 7 in thread

On 04.03.07 09:28:36, Kenneth Beck wrote:
> Fabrizio Angius wrote:
> >Visual studio refuses to link the main application with the dll and
> >complaints about some unresolved external symbols. Here is an example:
> >error LNK2001: unresolved external symbol "public: static struct
> >QMetaObject const MvdSharedData::staticMetaObject";
> >(?staticMetaObject@MvdSharedData@@2UQMetaObject@@B)
> >moc_movieeditor.obj
> >My DLL exports everything correctly and I can see that
> >MvdSharedData::staticMetaObject is actually being exported using an
> >object dump.
> >All my link errors are similar to this one
> >(someClass::staticMetaObject).
> >Adding the DLL-project moc_*.cpp files to the main application's
> >project in VS would solve the problem, but this is NOT a good
> >solution, as I should be able to link my DLL only using the headers
> >and the lib/dll files, not the MOC cpp files.
> >Any clues? Thanks guys!
> >PS: the DLL builds fine, I only have trouble linking it with my main
> >app!
> I do not think you LINK a dll! You load it at run time using the QLibrary.

Uhm, I might not be a windows professional, but you can do either just
like in Linux. A dll is a shared library, which means an application can
link to it, without copying its code into the apps executable. It can
also load the dll during runtime using QLibrary (which internally uses
some Microsoft mechanism to load the dll and execute its entry point),
but that is normally done only for plugins, where the app knows the
names of the dlls that need to be loaded only during runtime. 

Andreas

-- 
 [ signature omitted ] 

Message 8 in thread

I'm sorry but you are quite wrong ;)

You can use:

1) static linking (to make it short: the library code is copied into
your application code so you only have one huge binary)

2) dynamic linking. there are mainly two different ways to use shared
(or dynamic) libraries (I'm not going to talk about prelinking, load
time linking, implicit run-time linking and explicit run-time linking
;) :

  a) you have a dll, the library headers and a lib file that contains
(among other things) the symbols the library exports. the lib and
header files are used to embed the proper symbol resolution routines
in the application. the dll is actually loaded when you run the
application and everything behaves (almost) like with static linking

 b) you only have a dll. you will need to use some API calls like the
unix "dlopen" and "dlsym " or Qt's QLibrary to explicitly load the
library and resolve the symbols you will need. this is a good solution
for application plugins.


On Sun, 04 Mar 2007 09:28:36 -0600, Kenneth Beck <nekkceb@xxxxxxxxxxx>
wrote:

>I do not think you LINK a dll! You load it at run time using the QLibrary.

--
 [ signature omitted ] 

Message 9 in thread

Fabrizio Angius wrote:
> I'm sorry but you are quite wrong ;)
> 
> You can use:
> 
> 1) static linking (to make it short: the library code is copied into
> your application code so you only have one huge binary)
> 
> 2) dynamic linking. there are mainly two different ways to use shared
> (or dynamic) libraries (I'm not going to talk about prelinking, load
> time linking, implicit run-time linking and explicit run-time linking
> ;) :
> 
>   a) you have a dll, the library headers and a lib file that contains
> (among other things) the symbols the library exports. the lib and
> header files are used to embed the proper symbol resolution routines
> in the application. the dll is actually loaded when you run the
> application and everything behaves (almost) like with static linking
> 
>  b) you only have a dll. you will need to use some API calls like the
> unix "dlopen" and "dlsym " or Qt's QLibrary to explicitly load the
> library and resolve the symbols you will need. this is a good solution
> for application plugins.
> 
> 
> On Sun, 04 Mar 2007 09:28:36 -0600, Kenneth Beck <nekkceb@xxxxxxxxxxx>
> wrote:
> 
>> I do not think you LINK a dll! You load it at run time using the QLibrary.
Sorry, I was obvisouly wrong! My only experience is as described by 
Andreas, I use DLL as plugins, the app figures out which ones are 
available at run time, then loads using QLibrary. That works really well 
for me, but may not be platform independent!

--
 [ signature omitted ] 

Message 10 in thread

On 04.03.07 10:25:19, Kenneth Beck wrote:
> then loads using QLibrary. That works really well for me, but may not be 
> platform independent!

QLibrary is platform independent, thats one of the main reasons to use
it, else you could use dlopen (or the MS equivalent on windows)
directly.

Andreas

-- 
 [ signature omitted ] 

Message 11 in thread

A little update:

the problem is that the DLL does not export the staticMetaObject
methods of my QObject subclasses.

Example:

class MOVIDA_EXPORT MyClass: public QObject {
	Q_OBJECT
public: //........
}


From moc_myclass.cpp:

const QMetaObject MyClass::staticMetaObject = {
    { &QObject::staticMetaObject, qt_meta_stringdata_MyClass,
      qt_meta_data_MyClass, 0 }

..> this method is not being exported but visual studio pretends to
resolve this symbol when linking the application that links the DLL
(with MyClass). This is the reason why including the moc_myclass.cpp
file again in the main application project would fix the problem.

ANY CLUES? The method should either be exported or not being
referenced by the main application, I suppose.


PS: here is the movida_export define:

#  ifndef MOVIDA_EXPORT
#  ifdef Q_OS_WIN
#    define MOVIDA_EXPORT __declspec(dllexport)
#  elif defined(QT_VISIBILITY_AVAILABLE)
#    define MOVIDA_EXPORT __attribute__((visibility("default")))
#  endif
#  endif
#  ifndef MOVIDA_EXPORT
#    define MOVIDA_EXPORT
#  endif

--
 [ signature omitted ] 

Message 12 in thread

Hi,

> From moc_myclass.cpp:
> 
> const QMetaObject MyClass::staticMetaObject = {
>     { &QObject::staticMetaObject, qt_meta_stringdata_MyClass,
>       qt_meta_data_MyClass, 0 }
> 
> ..> this method is not being exported but visual studio pretends to

Mmmh... But I think it *is* exported - the whole class is exported. It's 
not a method by the way, it's a member variable of type struct QMetaObject.

> resolve this symbol when linking the application that links the DLL
> (with MyClass). This is the reason why including the moc_myclass.cpp
> file again in the main application project would fix the problem.
> 
> ANY CLUES? The method should either be exported or not being
> referenced by the main application, I suppose.

I usually don't work with Qt on the Windows platform, so don't take my 
word for it, but I again I think the symbol is exported.

> PS: here is the movida_export define:
> 
> #  ifndef MOVIDA_EXPORT
> #  ifdef Q_OS_WIN
> #    define MOVIDA_EXPORT __declspec(dllexport)
> #  elif defined(QT_VISIBILITY_AVAILABLE)
> #    define MOVIDA_EXPORT __attribute__((visibility("default")))
> #  endif
> #  endif
> #  ifndef MOVIDA_EXPORT
> #    define MOVIDA_EXPORT
> #  endif

Maybe you should add such a line for the case where the library is imported:
	#define MOVIDA_EXPORT __declspec(dllimport)

--
 [ signature omitted ] 

Message 13 in thread

yes, staticMetaObject it is actually exported (and it is a struct, not
a method, sorry for that error).
every time I see the object dump i seem to be missing something ;)

anyway, the issue remains and visual studio won't resolve those
symbols when linking the DLL.
and I don't understand how a dllimport should change things.
all the remaining symbols are resolved correctly, only that
staticMetaCrap is not ;)

I'm not really worried about it as I won't be supporting commercial
compilers for this specific project, but I want to know what's wrong
;)

--
 [ signature omitted ] 

Message 14 in thread

Fabrizio Angius schrieb:
> ...
> anyway, the issue remains and visual studio won't resolve those
> symbols when linking the DLL.
> and I don't understand how a dllimport should change things.

I don't know either. But that's how Microsoft has designed their usage
of DLLs, so you're on the safe side to use it:

- In your DLL: use dllexport
- Outside your DLL: use dllimport

The standard way is to use something like:

// MyLibDll.h
#ifdef WIN32
  // The following ifdef block is the standard way of creating macros
which make exporting
  // from a DLL simpler. All files within this DLL are compiled with the
MYLIB_EXPORTS
  // symbol defined on the command line. this symbol should not be
defined on any project
  // that uses this DLL. This way any other project whose source files
include this file see
  // MYLIB_API functions as being imported from a DLL, whereas this DLL
sees symbols
  // defined with this macro as being exported.
  #ifdef MYLIB_EXPORTS
    #define MYLIB_API __declspec(dllexport)
  #else
    #define MYLIB_API __declspec(dllimport)
  #endif

#else
  // define MYLIB_API to be "nothing"
  #define MYLIB_API
#endif

and in your actual class in the "MyLib":

#include <QtCore/QObject>
#inlude "MyLibDll.h"

class MYLIB_API MyLib : public QObject
{
  // don't forget to include the moc_MyLib.cpp in your DLL!
  Q_OBJECT
public:
  ...
};


but as it seems you already have a macro MOVIDA_EXPORT which I assume is
defined as above. So my best bet is you didn't compile the moc_*.cpp
into your DLL (or forgot the actual moc step, check your *.h custom
build steps in Visual Studio and see if they're actually performed;
maybe your moc_*.cpp files are out of date?).

> all the remaining symbols are resolved correctly, only that
> staticMetaCrap is not ;)

Make you sure that you also compile in those moc_*.cpp files into your DLL.

Good luck, Oliver

p.s. I can assure you that linking "QObject based classes in DLLs" with
your *.exe works, even with Visual Studio ;)


--
 [ signature omitted ] 

Message 15 in thread

Fabrizio Angius schrieb:
> ..
> PS: here is the movida_export define:
> 
> #  ifndef MOVIDA_EXPORT
> #  ifdef Q_OS_WIN
> #    define MOVIDA_EXPORT __declspec(dllexport)
> #  elif defined(QT_VISIBILITY_AVAILABLE)
> #    define MOVIDA_EXPORT __attribute__((visibility("default")))
> #  endif
> #  endif
> #  ifndef MOVIDA_EXPORT
> #    define MOVIDA_EXPORT
> #  endif

Ah, didn't see this post before. But this is *not* the standard way of
defining such export macros (create a DLL project with sample code in
Visual Studio as to refer to what I mean by "standard method" - it
creates a header with a macro definition as in my previous post).

Anyway, I've just checked in my actual code, exporting the whole
"QObject derived class" definitively *works*! Alternatively you could
only export the really needed methods/symbols (which makes your DLL
slightly smaller, too ;)

class MyClass : QObject
{
  Q_OBJECT
public:
  MYCLASS_API MyClass();
  MYCLASS_API virtual ~MyClass();

  MYCLASS_API int doSomething();
  MYCLASS_API int publicSymbol;
  ...
  // don't export this "internal" (but public) method
  void thisMethodIsInternalToThisDLL();
protected:

  // you *can* export protected methods; only then can you
  // derive from this class in *other* DLLs and use those
  // protected methods
  MYCLASS_API void thisMethodCanBeUsedFromDerivedClasses();
  void thisMethodCanOnlyBeUsedInDerivedClassesInThisDLL();

private:
  // no need to export private methods - they are "private"
  // after all ;)
  void doAnotherThing();
};

Like this you actually get another level of visibility, "DLL
visibility", apart from the public/protected/private mechanism :)

And again I can assure you that *both* approaches ("Export the whole
class" vs. "Export selected symbols only") work in Visual Studio, I've
just checked in my actual code.


Side note: At least with an older Visual Studio (I think it was way back
with Visual Studio 6.0) there was a case when you *had* to export the
whole class:

// entire class needs to be exported (Visual Studio 6.0)
class MYCLASS_API MyClass
{
public:
  MyClass();
  virtual ~MyClass();

private:
  // the template class here needs to be exported, even though
  // it is in the private scope!
  QVector<int> m_theVector;
};

I don't know the error message produced by the compiler when you only
exported the public methods... but anyway, this issue has gone away with
Visual Studio 2005 for sure, so the following works now, too:

// works now with Visual Studio 2005
class MyClass
{
public:
  MYCLASS_API MyClass();
  MYCLASS_API virtual ~MyClass();
  ...
private:
  QVector<int> m_theVector;
};


Attachement: Header files of actually working (test) code of mine, for
reference. They are part of a DLL. The "AxelClient.h" is "mocced" and
the moc_AxelClient.cpp is compiled into the AxelClient.dll which is then
linked against the *.exe application.
#ifndef __AXEL_CLIENT_DLL_H_
#ifndef __AXEL_CLIENT_DLL_H_
#define __AXEL_CLIENT_DLL_H_

#ifdef WIN32
#pragma warning( disable:4251 ) // Win32: don't report "needs DLL interface" warnings
                                // for private members 
#endif

#if defined(WIN32)

/*
	The following ifdef block is the standard way of creating macros which make exporting
	from a DLL simpler. All files within this DLL are compiled with the AXELCLIENT_EXPORTS
	symbol defined on the command line. this symbol should not be defined on any project
	that uses this DLL. This way any other project whose source files include this file see
	AXELCLIENT_API functions as being imported from a DLL, wheras this DLL sees symbols
	defined with this macro as being exported.
*/
	#ifdef AXELCLIENT_EXPORTS
		#define AXELCLIENT_API __declspec(dllexport)
	#else
		#define AXELCLIENT_API __declspec(dllimport)
	#endif

#else

	/* for all other platforms AXELCLIENT_API is defined to be "nothing" */
	#define AXELCLIENT_API
	
#endif

#endif // __AXEL_CLIENT_DLL_H_

// Some Emacs-Hints -- please don't remove:
//
//  Local Variables:
//  mode:C++
//  tab-width:4
//  End:
#ifndef __AXEL_CLIENT_H_
#ifndef __AXEL_CLIENT_H_
#define __AXEL_CLIENT_H_

#include <QtCore/QObject>

#include "AxelClientDll.h"

class ClientParser;

/*!
 * \brief AXEL client remote methods.
 *
 * <table class="authorinfo" border="0">
 *   <tr>
 *     <th>Creator</th>
 *     <td>@author Oliver Knoll</td>
 *     <td>@version 1.0</td>
 *   </tr>
 *   <tr>
 *     <th>Last modified</th>
 *     <td>$Author: ok $</td>
 *     <td>$Revision: 4615 $</td>
 *   </tr>
 * </table>
 */
class AxelClient : public QObject
{
    Q_OBJECT

public:
    AXELCLIENT_API AxelClient();
    AXELCLIENT_API ~AxelClient();
    
    /*!
     * \param size
     *        size of the BLOB [MB]
     */
    AXELCLIENT_API int getBlob (const char *host, const int port, const int size);

private:
    ClientParser *m_parser;
    bool         m_hasAnswer;

private slots:
    void handleBlobAnswer (unsigned char *data, int size);
    void handleReadyRead();

};

#endif // __AXEL_CLIENT_H_

// Some Emacs-Hints -- please don't remove:
//
//  Local Variables:
//  mode:C++
//  tab-width:4
//  End:

Pages: Prev | 1 | 2 | 3 | Next