-
Notifications
You must be signed in to change notification settings - Fork 69
Description
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 hereThe 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.