[Kde-bindings] QtRuby: Qt::Variant#value fails for ushort and QChar variants

Yaohan Chen yaohan.chen at gmail.com
Wed Apr 11 18:42:11 UTC 2012


With those changes the workaround specs still work for me. According to unpack
documentation, "N" is the same as "L>" or big-endian unsigned 32-bit integer, and
"n" is the same as "S>" or big-endian unsigned 16-bit integer. So the int and QChar
workarounds were failing for you because they were using signed integers instead, and
the ushort workaround should have been working as the way I wrote it. Since the numbers
were all positive, I think the unsigned and signed versions should have been the same
though. I don't really know how to explain that, but I'm pretty sure the workarounds
bypass QtRuby altogether so it's probably unimportant.


Yaohan Chen


On Wednesday, April 11, 2012 05:27:37 PM Richard Dale wrote:
> On Wednesday, April 11, 2012 11:56:44 AM Yaohan Chen wrote:
> > 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!
> I got the workround to work after a bit of experimenting. I needed to change 
> the unpack strings to '@5N>' for the first test and then '@5n>' for the next 
> two. So it does look like it is something to do with the expected endianess.
> 
> -- Richard
> 
> 
> > 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
> > 
> > _______________________________________________
> > Kde-bindings mailing list
> > Kde-bindings at kde.org
> > https://mail.kde.org/mailman/listinfo/kde-bindings
> _______________________________________________
> 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