[Kde-bindings] QtRuby: Qt::Variant#value fails for ushort and QChar variants
Yaohan Chen
yaohan.chen at gmail.com
Wed Apr 11 15:56:44 UTC 2012
Thanks for the quick response. I wonder if the workarounds fail because of
endian/size difference on your machine. I did try with "native endian" (_
instead of > at the end of unpack argument), but that makes them fail for me.
Anyway I wrote them only based on experiment and I haven't found more detailed
specification of QDataStream format. It's great that the workarounds will
be no longer necessary!
Yaohan Chen
On Wednesday, April 11, 2012 01:40:48 PM Richard Dale wrote:
> On Wednesday, April 11, 2012 03:11:33 AM Yaohan Chen wrote:
> > Hello,
> >
> > I'm getting a segfault when calling Qt::Variant#value for QVariant<ushort>,
> > and NoMethodError for QVariant<QChar>. I've included test cases that show
> > the failures as well as workaround using String#unpack below. They require
> > RSpec, RubyInline and of course QtRuby to run. Could anyone confirm if you
> > have the same problem?
> >
> > Thanks,
> >
> > Yaohan Chen
> >
> >
> > #!/usr/bin/env rspec
> >
> > require 'Qt'
> > require 'inline'
> >
> > # These tests demonstrate that when you get a Qt::Variant by unserializing a
> > serialized # QVariant via QDataStream, the value method fails if the
> > variant's type is QChar or ushort. describe 'Qt::Variant#value' do
> > it 'returns the value of an int variant' do
> > variant = unserialize_variant SerializedVariant.of_int(15)
> > # This one works for me
> > variant.value.should == 15
> > end
> >
> > it 'returns the value of a QChar variant' do
> > variant = unserialize_variant SerializedVariant.of_QChar(10)
> > # This fails for me saying the QVariant does not have method toChar
> > defined variant.value.should == 10
> > end
> >
> > it 'returns the value of a ushort variant' do
> > variant = unserialize_variant SerializedVariant.of_ushort(5)
> >
> > # pending 'causes segfault'
> >
> > # This causes Ruby to segfault for me. If it happens for you too,
> > uncomment the pending # line above so RSpec can report the results of other
> > examples. variant.value.should == 5
> > end
> > end
> >
> > # These extract Ruby values directly from serialized variants without Qt, to
> > show that the # correct data is passed from C++ to Ruby. They use
> > String#unpack and skip the first # 5 bytes ('@5') which are QVariant's type
> > information and "null flag". See #
> > https://qt-project.org/doc/qt-4.8/datastreamformat.html
> > describe 'Workaround using String#unpack' do
> > it 'returns the value of an int variant' do
> > string = SerializedVariant.of_int(15);
> > # l> for big-endian 32bit signed integer
> > string.unpack('@5l>').first.should == 15
> > end
> >
> > it 'returns the value of a QChar variant' do
> > string = SerializedVariant.of_QChar(10);
> > # s> for big-endian 16bit signed integer (QChar stores a UTF-16
> > character) string.unpack('@5s>').first.should == 10
> > end
> >
> > it 'returns the value of a ushort variant' do
> > string = SerializedVariant.of_ushort(5);
> > # S> for big-endian 16bit unsigned integer
> > string.unpack('@5S>').first.should == 5
> > end
> > end
> >
> > # Given string containing serialization of a variant, return the variant
> > def unserialize_variant(string)
> > byte_array = Qt::ByteArray.new string
> > data_stream = Qt::DataStream.new byte_array
> > variant = Qt::Variant.new
> > data_stream >> variant
> > variant
> > end
> >
> > # This module contains functions that return serialization of several
> > variant types module SerializedVariant
> > inline :C do |builder|
> > builder.add_compile_flags %w[-x c++]
> > builder.include '<QtCore/QByteArray>'
> > builder.include '<QtCore/QDataStream>'
> > builder.include '<QtCore/QVariant>'
> > builder.add_link_flags %w[-lQtCore]
> >
> > builder.prefix <<-CODE
> > // Return serialization of the given QVariant
> > VALUE serialize(QVariant variant) {
> > QByteArray byte_array;
> > QDataStream data_stream(&byte_array, QIODevice::WriteOnly);
> > data_stream << variant;
> > return rb_str_new(byte_array.data(), byte_array.size());
> > }
> > CODE
> >
> > # :expand_types => true makes RubyInline insert VALUE self and figure
> > arity automatically builder.c_raw_singleton <<-CODE, :expand_types => true
> > // Return serialization of a QVariant containing the given int
> > VALUE of_int(VALUE v) {
> > QVariant variant = QVariant::fromValue<int>(FIX2INT(v));
> > return serialize(variant);
> > }
> > CODE
> >
> > builder.c_raw_singleton <<-CODE, :expand_types => true
> > // Return serialization of a QVariant containing the given QChar
> > VALUE of_QChar(VALUE v) {
> > QVariant variant = QVariant::fromValue<QChar>(FIX2INT(v));
> > return serialize(variant);
> > }
> > CODE
> >
> > builder.c_raw_singleton <<-CODE, :expand_types => true
> > // Return serialization of a QVariant containing the given ushort
> > VALUE of_ushort(VALUE v) {
> > QVariant variant = QVariant::fromValue<ushort>(FIX2INT(v));
> > return serialize(variant);
> > }
> > CODE
> > end
> > end
>
> Thanks for the bug report and the very interesting test program. I installed
> RubyInline to get it working and I'm really impressed how you can combine C
> code and ruby in the same source. QtRuby has never really had any test code
> and I think for the next version 3.0 it would be nice to do some tests using
> RSpec/RubyInline like you've done.
>
> I've fixed the bug in Qt::Variant#value in the master branch. I needed to
> change the QChar comparison to:
>
> it 'returns the value of a QChar variant' do
> variant = unserialize_variant SerializedVariant.of_QChar(10)
> # This fails for me saying the QVariant does not have method toChar defined
> variant.value.should == Qt::Char.new(10)
> end
>
> The three workround tests don't work for me though and they still fail, and I
> don't know if that is a problem with QtRuby or the test code.
>
> -- Richard
> -- Richard
>
>
>
> _______________________________________________
> Kde-bindings mailing list
> Kde-bindings at kde.org
> https://mail.kde.org/mailman/listinfo/kde-bindings
More information about the Kde-bindings
mailing list