Skip to content

Split a library into multiple modules cannot work properly on Windows (msys2/mingw) #355

@souk4711

Description

@souk4711

Issue Description

The Qt library has multiple modules, such as QtCore, QtGui, etc. So I create a gem for each module, such as rubyqt6-qtcore, rubyqt6-qtgui, etc. (rubyqt6-qtgui depends on rubyqt6-core)

It works fine on Linux. But cause some runtime exceptions, like Type QObject is not defined ..., on Windows. Seems the DLL does not share global variables, and does not export any symbols. ref - difference between .so and .dll

In rubyqt6-qtcore:

void Init_qobject(Rice::Module rb_mQt6QtCore)
{
    rb_cQObject = define_class_under<QObject>(rb_mQt6QtCore, "QObject")
        // define methods here.
 }

In rubyqt6-qtgui:

void Init_qaction(Rice::Module rb_mQt6QtGui)
{
    rb_cQAction = define_class_under<QAction, QObject>(rb_mQt6QtGui, "QAction")
        // define methods here

The program load qtcore.so successfully, then load qtgui.so, but raises an exception.

I think, on windows, each DLL holds a copy of Rice::detail::Registries::instance. The Registries::instance in qtgui.so cannot getType of QObject which registered in qtcore.so.


First Try (failed)

Try to redefine class QObject on qtgui.so.

It loads successfully. But got Wrong argument type. Expected RubyQt6::QtCore::QObject. Recevied RubyQT6::QtCore::QObject exception when invoking QObject#meth (the method QObject#meth defined in the copy in qtcore.so).

void Init_qaction(Rice::Module rb_mQt6QtGui, rb_mQt6QtCore)
{
    define_class_under<QObject>(rb_mQt6QtCore, "QObject")
      .define_constructor<Constructor>(...);  # required, cuz `klass.undef_creation_funcs();`
      # no more method define.

    rb_cQAction = define_class_under<QAction, QObject>(rb_mQt6QtGui, "QAction")
        ...

Second Try (failed)

Try to DLL export Rice::detail::Registries::instance in qtcore.so, and DLL import Rice::detail::Registries::instance in qtgui.so. I think this makes Registries::instance only one copy.

#ifdef _WIN32
#  ifdef RUBYQT6_BUILD_QTCORE_LIB
#    define RICE_EXPORT __declspec(dllexport)
#    define RICE_LIBRARY_INIT 1
#  else
#    define RICE_EXPORT __declspec(dllimport)
#    define RICE_LIBRARY_INIT 0
#  endif
# ...
#endif

namespace Rice::detail
{
  class RICE_EXPORT Registries
  {
  public:
    static RICE_EXPORT Registries instance;
....

#if RICE_LIBRARY_INIT == 1
  //Initialize static variables here.
  inline Registries Registries::instance;
#endif
}

But it still doesn't work. Seems Data_Type<T>::check_is_bound() returns false because klass_ is nil. And it does not seem possible to DLL export Data_Type<T> because Rice automatically defines some raw types (e.g. Pointer<int>, Pointer<QObject>) when defining methods.


Any advice on how to get the rice to work with multiple modules on Windows ?

Thx.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions