I am working on a feature for an application that has to run on JRuby. Out of habit I develop on 'Native' Ruby. When I try to run any methods from this class in JRuby I get error messages like:
MissingSourceFile: no such file to load -- serialport
I think the problem lies in in the require 'serialport.so'. Is there a way to make this work in JRuby? Is there another way to require a .so file? Or a gem that can work with JRuby to provide the SerialPort class? I tried installing the ruby-serialport gem but that doesn't seem to install properly (Windows nmake issues).
Here is what my class file looks like:
require 'serialport.so'
class AlphaDisplay
#STATES
SOLID = "b"
ROTATE = "a"
BLINK = "c"
#COLORS
RED = "1"
GREEN = "2"
YELLOW = "3"
ORANGE = "7"
def self.message(address = 00, text = "ICS", color = AlphaDisplay::GREEN, state = AlphaDisplay::SOLID)
address = address.to_s
if address.length == 1
address = "0#{address}"
end
string = 1.chr + 90.chr + address + 2.chr + 65.chr + 65.chr + 27.chr + 26.chr + state + 28.chr + color + text + 4.chr
return string
end
def self.test(address = 00, text = "ICS", color = AlphaDisplay::GREEN, state = AlphaDisplay::SOLID)
sp = SerialPort.new(0, 9600, 8, 1, SerialPort::NONE)
sp.write(message(address,text,color,state))
sp.close
end
end
def SerialPort::new(port, *params)
sp = create(port)
begin
sp.set_modem_params(*params)
rescue
sp.close
raise
end
return sp
end
def SerialPort::open(port, *params)
sp = create(port)
begin
sp.set_modem_params(*params)
if (block_given?)
yield sp
sp.close
return nil
end
rescue
sp.close
raise
end
return sp
end
As far as I know, JRuby doesn't provide any native emulation layer, just the Ruby interpreter in Java. The problem is that ".so" files are UNIX specific and cannot run on Windows without some sort of emulation/translation.
You're better off avoiding Ruby libraries which require native extensions if you're going to use JRuby.
Related
I'm trying to generate Bitcoin addresses in ruby by using this guide:
https://bhelx.simst.im/articles/generating-bitcoin-keys-from-scratch-with-ruby/
But something isn't quite right, because the addresses being generated aren't coming out quite right.
Here's the class I'm using:
require 'openssl'
require 'ecdsa'
require 'securerandom'
require 'base58'
class BitcoinAddressGenerator
ADDRESS_VERSION = '00'
def self.generate_address
# Bitcoin uses the secp256k1 curve
curve = OpenSSL::PKey::EC.new('secp256k1')
# Now we generate the public and private key together
curve.generate_key
private_key_hex = curve.private_key.to_s(16)
puts "private_key_hex: #{private_key_hex}"
public_key_hex = curve.public_key.to_bn.to_s(16)
puts "public_key_hex: #{public_key_hex}"
pub_key_hash = public_key_hash(public_key_hex)
puts "pub_key_hash: #{pub_key_hash}"
address = generate_address_from_public_key_hash(public_key_hash(public_key_hex))
puts "address: #{address}"
end
def self.generate_address_from_public_key_hash(pub_key_hash)
pk = ADDRESS_VERSION + pub_key_hash
encode_base58(pub_key_hash + checksum(pub_key_hash))
end
def self.int_to_base58(int_val, leading_zero_bytes=0)
alpha = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
base58_val, base = '', alpha.size
while int_val > 0
int_val, remainder = int_val.divmod(base)
base58_val = alpha[remainder] + base58_val
end
base58_val
end
def self.encode_base58(hex)
leading_zero_bytes = (hex.match(/^([0]+)/) ? $1 : '').size / 2
("1"*leading_zero_bytes) + int_to_base58( hex.to_i(16) )
end
def self.checksum(hex)
sha256(sha256(hex))[0...8]
end
# RIPEMD-160 (160 bit) hash
def self.rmd160(hex)
Digest::RMD160.hexdigest([hex].pack("H*"))
end
def self.sha256(hex)
Digest::SHA256.hexdigest([hex].pack("H*"))
end
# Turns public key into the 160 bit public key hash
def self.public_key_hash(hex)
rmd160(sha256(hex))
end
end
It outputs something like:
private_key_hex: C96DE079BAE4877E086288DEDD6F9F70B671862B7E6E4FC0EC401CADB81EDF45
public_key_hex: 0422435DF80F62E643D3CFBA66194052EC9ED0DFB47A1B26A4731079A5FF84FBF98FF0A540B6981D75BA789E6192F3B38BABEF6B0286CAEB4CAFCB51BB96D97B46
public_key_hash: db34927cc5ec0066411f366d9a95f9c6369c6e1d
address: Lz3xnxx6Uh79PEzPpWSMMZJVWR36hJgVL
If I plug this address into blockchain.info and similar tools it says that it's an invalid address.
Any help would be greatly appreciated.
In your generate_address_from_public_key_hash method, the checksum should be over the hash including the address prefix. You’re not actually using the pk variable at all at the moment after you assign it. The code should look something like:
def self.generate_address_from_public_key_hash(pub_key_hash)
pk = ADDRESS_VERSION + pub_key_hash
encode_base58(pk + checksum(pk)) # Using pk here, not pub_key_hash
end
The mistake seems to also be on the page you link to, I guess the author must have made a copy/paste error.
As an aside, keeping everything in hex strings and decoding back and forth seems an odd way of doing this. I would have thought it would be easier to use raw binary strings, and only encode to hex when printing out values.
I have a script that uses pdf-reader among other gems to parse and split up a large pdf file into multiple pdfs. I have been setting it up to run on a new machine, and am now getting this error when I try to run tests:
Failure/Error: SrnProcessor.process_main_pdf(main_pdf_path)
ArgumentError:
Unknown glyph width for 9 Helvetica
I saw that a couple other people are having this issue over here: https://github.com/yob/pdf-reader/issues/102 But no workarounds yet. It seems to me that this must be an issue with my setup and not the gem or the pdf, since on other machines I don't have any problems. I'm running ruby 1.9.3 on linux (Mageia 3 64bit), and have tried switching to multiple versions of the gem with no luck. Any suggestions on what I'm missing? Thanks!
I am having the same problem with ruby 1.9.3. I have narrowed it down for me at least to having the trademark R in the pdf. I got it down to this code in the pdf gem:
def glyph_width(code_point)
return 0 if code_point.nil? || code_point <= 0
m = #metrics.char_metrics_by_code[code_point]
if m.nil?
names = #font.encoding.int_to_name(code_point)
m = names.map { |name|
#metrics.char_metrics[name.to_s]
}.compact.first
end
if m
m[:wx]
elsif #font.widths[code_point - 1]
#font.widths[code_point - 1]
else
raise ArgumentError, "Unknown glyph width for #{code_point} #{#font.basefont}"
end
end
and i changed it to this which will just ignore characters that it cant recognize. I'm not sure if ruby 2.0 has fixed this issue or not.
def glyph_width(code_point)
return 0 if code_point.nil? || code_point <= 0
m = #metrics.char_metrics_by_code[code_point]
if m.nil?
names = #font.encoding.int_to_name(code_point)
m = names.map { |name|
#metrics.char_metrics[name.to_s]
}.compact.first
end
if m
m[:wx]
elsif #font.widths[code_point - 1]
#font.widths[code_point - 1]
elsif(m == nil)
return 0
else
p(m)
raise ArgumentError, "Unknown glyph width for #{code_point} #{#font.basefont}"
end
end
A better solution might be to catch the code_point which in this case is 9 in the char_metrics_by_code
I just started learning Ruby last week, so please bear with me on this.
I'm using Ruby 1.9.3. I have problem trying to get my unit test to run, and I've been trying for the past 2 days, but I haven't been able to successfully run my unit test.
Here's the code for my simple calculator class:
class Calc
def initialize
end
def Add(leftOp, rightOp)
return (leftOp + rightOp)
end
def Sub(leftOp, rightOp)
return (leftOp - rightOp)
end
def Div(leftOp, rightOp)
if(rightOp == 0)
raise ArgumentError.new("Divided by 0")
else
return (leftOp / rightOp)
end
def Mult(leftOp, rightOp)
return (leftOp * rightOp)
end
end
myCalc = Calc.new
puts "2 + 3 = " + myCalc.Add(2, 3).to_s
puts "2 - 3 = " + myCalc.Sub(2, 3).to_s
puts "2 * 3 = " + myCalc.Mult(2, 3).to_s
puts "6 / 3 = " + myCalc.Div(6, 3).to_s
puts "10 / 0 = " + myCalc.Div(10, 0).to_s
This works fine. All the outputs are printed out as expected. Now, I want to write a unit test for this class. Below is the code for the unit test:
require 'test/unit'
require 'test/unit/ui/console/testrunner'
require 'Calc'
class Test_Calc < Test::Unit::TestCase
def setup
myCalc = Calc.new
#result_1 = myCalc.Add(5, 8)
#result_2 = myCalc.Sub(9, 15)
#result_3 = myCalc.Mult(8, 6)
#result_4 = myCalc.Div(18, 3)
#result_5 = myCalc.Div(2, 0)
end
def test_Add
assert_equal(#result_1, 13)
end
def test_Sub
assert_equal(#result_2, -6)
end
def test_Mult
assert_equal(#result_3, 48)
end
def test_Div
assert_equal(#result_4, 6)
end
def test_Div_Zero
assert_match("\Divided by 0\", e.message)
end
end
Test::Unit::UI::Console::TestRunner.run(Test_Calc)
When I ran this unit test, it spit out this error
The Calc.rb file is in the very same directory of the test_Calc.rb file. Why doesn't it see it? I even tried to copy the Calc.rb file to the same directory of the "custom_require.rb" file ("lib/ruby/site_ruby/1.9.1/rubygems"), but that didn't help.
After searching all over the web, I learned that Test::Unit has been removed and replaced by MiniTest (!). So, I tried the MiniTest thing as followed:
require 'minitest/unit'
require 'Calc'
class Test_Calc < MiniTest::Unit::TestCase
#Test_Calc definition
end
MiniTest::Unit.autorun
I still got back the exact same error as before, so maybe I was doing something wrong with the MiniTest thing.
I even followed the example from the following site, but it didn't seem to work in my case. Even if I have a fully defined class (Calc.rb), I still got the "Calc - (LoadError)".
http://www.ibm.com/developerworks/opensource/tutorials/os-ruby1/section3.html
After searching all over the web again, I learned that test::unit was available as a gem for backward compatibility, and so I downloaded and install test-unit-2.5.4.gem from the link below:
http://rubygems.org/gems/test-unit
Even after installing the gem, it still didn't work (I checked to ensure that the gem was installed in "Ruby193\lib\ruby\gem\1.9.1\gems"). Ruby still complained that it "cannot load such file -- Calc (LoadError)"
So, how do I run the test unit? What am I missing?
Thank you in advance for your help.
Updated:
After including ".\Calc" as Blaine suggested, I got the following new error message:
Well, at least, it recognizes the Calc class this time, and it started loading the test suite.
First, if the program says it can't find the file, make your require look like this: require './Calc'
Second, make sure you are using the latest version of the minitest gem. You can check this by doing:
gem list
The version will be on the right of the list. As of today the current version is 4.6.1. If your version is not correct, update it by doing:
gem install --version '4.6.1' (or whatever the version is)
I need to show some treeview item text striked out text into a QT treeview from Ruby.
After some reading on QT documentation and much coding, I found that only when rendering font in bold, also the strikeout was rendered.
So I wonder, where I'm doing wrong?
This is the code to achive the result shown above. Note as I set strikeout for every even row item.
I'm using Ruby 1.8.7 and Qt 4.6.2 and qt4ruby 4.4.3-6 on Mandriva Linux.
require 'Qt4'
require 'date'
class MyStandardItem < Qt::StandardItem
def initialize(str = nil)
super str
end
def data(role = Qt::UserRole + 1)
return super(role) unless role == Qt::FontRole
ret_val = Qt::Font.new()
#parameters for "fromString":font family, pointSizeF, pixelSize, QFont::StyleHint, QFont::Weight, QFont::Style, underline, strikeOut, fixedPitch, rawMode
ret_val.fromString "sans serif,-1,-1,0,0,0,0,0,0,0"
case role
when Qt::FontRole
ret_val.setStrikeOut(true) if (index.row % 2) == 0
if index.column == 1
ret_val.weight = Qt::Font.Bold
else
ret_val.weight = Qt::Font.Normal
end
return Qt::Variant.fromValue(ret_val)
end
return ret_val
end
end
Qt::Application.new(ARGV) do
treeview = Qt::TreeView.new do
model = Qt::StandardItemModel.new self
head = [MyStandardItem.new "Qt v. #{Qt.version}"]
head << MyStandardItem.new("Ruby v. #{VERSION}")
head << MyStandardItem.new("Qt4Ruby v. 4.4.3-6 (Mandriva)")
model.append_row head
(1..10).each do |i|
col0 = MyStandardItem.new 'some text'
col0.check_state = ((i % 3) == 0)? Qt.Checked : Qt.Unchecked
col0.checkable = true
col0.editable= false
col1 = MyStandardItem.new "line ##{i}"
col2 = MyStandardItem.new((Date.today + i).strftime '%d/%m/%y')
model.append_row [col0, col1, col2]
end
self.model = model
show
end
exec
end
Eventually I find an hackish trick to overcome this problem. Playing around after reading again the enum QFont::Weight description I tried to set
ret_val.weight = 51 # Qt::Font.Normal value is 50
instead of
ret_val.weight = Qt::Font.Normal
and magically the normal text appears striked out!
Maybe this strange behaviour is due to a bug on QT?
I'm looking for an easy way to get width and height dimensions for image files in Ruby without having to use ImageMagick or ImageScience (running Snow Leapard).
As of June 2012, FastImage which "finds the size or type of an image given its uri by fetching as little as needed" is a good option. It works with local images and those on remote servers.
An IRB example from the readme:
require 'fastimage'
FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
=> [266, 56] # width, height
Standard array assignment in a script:
require 'fastimage'
size_array = FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
puts "Width: #{size_array[0]}"
puts "Height: #{size_array[1]}"
Or, using multiple assignment in a script:
require 'fastimage'
width, height = FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
puts "Width: #{width}"
puts "Height: #{height}"
You could try these (untested):
http://snippets.dzone.com/posts/show/805
PNG:
IO.read('image.png')[0x10..0x18].unpack('NN')
=> [713, 54]
GIF:
IO.read('image.gif')[6..10].unpack('SS')
=> [130, 50]
BMP:
d = IO.read('image.bmp')[14..28]
d[0] == 40 ? d[4..-1].unpack('LL') : d[4..8].unpack('SS')
JPG:
class JPEG
attr_reader :width, :height, :bits
def initialize(file)
if file.kind_of? IO
examine(file)
else
File.open(file, 'rb') { |io| examine(io) }
end
end
private
def examine(io)
raise 'malformed JPEG' unless io.getc == 0xFF && io.getc == 0xD8 # SOI
class << io
def readint; (readchar << 8) + readchar; end
def readframe; read(readint - 2); end
def readsof; [readint, readchar, readint, readint, readchar]; end
def next
c = readchar while c != 0xFF
c = readchar while c == 0xFF
c
end
end
while marker = io.next
case marker
when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers
length, #bits, #height, #width, components = io.readsof
raise 'malformed JPEG' unless length == 8 + components * 3
when 0xD9, 0xDA: break # EOI, SOS
when 0xFE: #comment = io.readframe # COM
when 0xE1: io.readframe # APP1, contains EXIF tag
else io.readframe # ignore frame
end
end
end
end
There's also a new (July 2011) library that wasn't around at the time the question was originally asked: the Dimensions rubygem (which seems to be authored by the same Sam Stephenson responsible for the byte-manipulation techniques also suggested here.)
Below code sample from project's README
require 'dimensions'
Dimensions.dimensions("upload_bird.jpg") # => [300, 225]
Dimensions.width("upload_bird.jpg") # => 300
Dimensions.height("upload_bird.jpg") # => 225
There's a handy method in the paperclip gem:
>> Paperclip::Geometry.from_file("/path/to/image.jpg")
=> 180x180
This only works if identify is installed. If it isn't, if PHP is installed, you could do something like this:
system(%{php -r '$w = getimagesize("#{path}"); echo("${w[0]}x${w[1]}");'})
# eg returns "200x100" (width x height)
I have finally found a nice quick way to get dimensions of an image. You should use MiniMagick.
require 'mini_magick'
image = MiniMagick::Image.open('http://www.thetvdb.com/banners/fanart/original/81189-43.jpg')
assert_equal 1920, image[:width]
assert_equal 1080, image[:height]
libimage-size is a Ruby library for calculating image sizes for a wide variety of graphical formats. A gem is available, or you can download the source tarball and extract the image_size.rb file.
Here's a version of the JPEG class from ChristopheD's answer that works in both Ruby 1.8.7 and Ruby 1.9. This allows you to get the width and height of a JPEG (.jpg) image file by looking directly at the bits. (Alternatively, just use the Dimensions gem, as suggested in another answer.)
class JPEG
attr_reader :width, :height, :bits
def initialize(file)
if file.kind_of? IO
examine(file)
else
File.open(file, 'rb') { |io| examine(io) }
end
end
private
def examine(io)
if RUBY_VERSION >= "1.9"
class << io
def getc; super.bytes.first; end
def readchar; super.bytes.first; end
end
end
class << io
def readint; (readchar << 8) + readchar; end
def readframe; read(readint - 2); end
def readsof; [readint, readchar, readint, readint, readchar]; end
def next
c = readchar while c != 0xFF
c = readchar while c == 0xFF
c
end
end
raise 'malformed JPEG' unless io.getc == 0xFF && io.getc == 0xD8 # SOI
while marker = io.next
case marker
when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers
length, #bits, #height, #width, components = io.readsof
raise 'malformed JPEG' unless length == 8 + components * 3
# colons not allowed in 1.9, change to "then"
when 0xD9, 0xDA then break # EOI, SOS
when 0xFE then #comment = io.readframe # COM
when 0xE1 then io.readframe # APP1, contains EXIF tag
else io.readframe # ignore frame
end
end
end
end
For PNGs I got this modified version of ChristopeD's method to work.
File.binread(path, 64)[0x10..0x18].unpack('NN')