On Wednesday 17 July 2013 21:42:04 Pali Rohár wrote:
> Hello,
> 
> I found problem in current plugin loader & plugins and need
> help how to solve it.
> 
> My current code have common "interface" classes for password
> and addressbook plugins. Because trojita working only with
> pointers of these common objects, code of interface classes
> must be statically linked into trojita executable binary.
> 
> But plugin implementation inherit from common interface class,
> so constructor (and other qobject moc methods) must be
> accessible from plugin shared library.
> 
> So there are two possible methods:
> 1. static link code of interface classes to both trojita
> executable and to plugin shared library
> 2. link interface code only to trojita executable and export
> symbols to be accessible by loaded libraries
> 
> My current code using option 1. because it does not need any
> hacks to cmake. But now I see that sometimes (when compiled as
> kontact shared library) qobject_cast<> from QObject* to
> PasswordInterface* provided by plugin not working and
> returning NULL. This cause that plugin is ignored as
> incompatible. But dynamic_cast<> operator working fine. Is
> this because both trojita executable and password plugin has
> linked code of
> PasswordInterface class?
> 
> I tried to rewrite cmake code to use option 2. It also needed
> to add more Q_DECL_IMPORT/EXPORT to current code...
> 
> But cmake code needs ugly hack -Wl,-whole-archive as somebody
> wrote here
> http://stackoverflow.com/questions/6054942/gcc-rdynamic-not-w
> orking-with-static-libraries and here
> http://www.mail-archive.com/[email protected]/msg01890.html
> 
> (plus some other cmake functions and properties - but all
> portable for cmake)
> 
> 
> Now I tried to compile trojita code to shared library for
> loading by KDE4 Kontact. But Kontact loading plugins without
> RTLD_GLOBAL and when Trojita started to loading its plugins,
> every plugin failed because of resolving some symbols (used
> by plugin which should export trojita shared library). I
> looked into Kontact code how loading plugins and it is not
> possible to add RTLD_GLOBAL flag (or
> QLibrary::ExportExternalSymbolsHint). This happen with option
> 2. When I used option 1 with dynamic_cast<> plugins worked
> fine. But qobject_cast<> not.
> 
> So questions are:
> 
> * what to do with c++ code which is part of plugin interfaces?
> Use option 1?
> 
> * how to solve issue when trojita is compiled as shared
> library (e.g. kontact kpart), started by other process
> (kontact) and needs to loads its plugins (trojita kwallet
> plugin)?

Now I found that shared library can be loaded via dlopen (in qt 
world by QLibrary) also more times and RTLD_LOCAL flag can be 
overwritten by RTLD_GLOBAL by another dlopen call.

Now I tried it and it really working. I opened kontact trojita 
library with RTLD_GLOBAL (=QLibrary::ExportExternalSymbolsHint) 
from already running code in kontact trojita library. And it 
really exported all symbols from this library to other libraries 
(passwords and addressbooks). Addressbook library was able to 
resolve symbol which was in kontact library. And also it worked 
with standalone trojita version.

So for option 2 (link all libraries statically to trojita 
executable and export some symbols for shared plugin libraries) 
only "-Wl,-whole-archive" flag is needed at compile link time.

What do you think? It is very bad to support (now) only GNU 
linker for plugins? Maybe other linkers/compilers has some flag 
too (or maybe they do not need it)... I can try to change CMake 
code to compile all plugins and trojita executable in this way.

I think this option is cleaner solution as creating some new 
shared library only for exporting symbols to other shared plugin 
libraries...

-- 
Pali Rohár
[email protected]

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to