Jump to content

Call a function in a shared library: Difference between revisions

→‎{{header|Ruby}}: Ruby 2.2 removed DL; switch from DL to Fiddle. Add example with ImageMagick. Make examples work when libraries are missing.
m (→‎{{header|zkl}}: remove comment)
(→‎{{header|Ruby}}: Ruby 2.2 removed DL; switch from DL to Fiddle. Add example with ImageMagick. Make examples work when libraries are missing.)
Line 1,245:
 
=={{header|Ruby}}==
This script uses Fiddle from Ruby's standard library to open <code>fakeimglib.so</code> from the [[#C|C example]].
Using the standard {{libheader|Ruby/DL}} library:
<lang ruby>require 'dl/import'
 
<lang ruby>require 'fiddle/import'
FakeImgLib = DL.dlopen("/path/to/fakeimg.so")
 
module FakeImageFakeImgLib
extend Fiddle::Importer
def self.openimage filename
begin
FakeImgLib["openimage", "IS"].call(filename)[0]
dlload './fakeimglib.so'
extern 'int openimage(const char *)'
rescue Fiddle::DLError
# Either fakeimglib or openimage() is missing.
@@handle = -1
def openimage(path)
$stderr.puts "internal openimage opens #{path}\n"
@@handle += 1
end
module_function :openimage
end
end
 
handle = FakeImageFakeImgLib.openimage("path/to/image")</lang>
puts "opened with handle #{handle}"</lang>
 
The next script tries to use ImageMagick. First, it tries [https://rmagick.github.io/ rmagick] from RubyGems. If that library is missing, it tries to use [http://wiki.github.com/ffi/ffi ffi] from RubyGems to call C functions in ImageMagick. (FFI is an alternative to Fiddle). If that doesn't work, it falls back to code that only handles PNG images.
Using the nicer {{libheader|RubyGems}} package [http://wiki.github.com/ffi/ffi ffi], following [[#C|C]] example
 
<lang ruby>require 'ffi'
{{libheader|ImageMagick}}
module FakeImgLib
{{libheader|RubyGems}}
extend FFI::Library
<lang ruby># This script shows the width x height of some images.
ffi_lib "path/to/fakeimglib.so"
# Example:
attach_function :openimage, [:string], :int
# $ ruby imsize.rb dwarf-vs-elf.png swedish-chef.jpg
# dwarf-vs-elf.png: 242x176
# swedish-chef.jpg: 256x256
 
begin
require 'rmagick'
lib = :rmagick
rescue LoadError
# Missing rmagick. Try ffi.
begin
require 'ffi'
module F
extend FFI::Library
ffi_lib 'MagickWand-6.Q16'
attach_function :DestroyMagickWand, [:pointer], :pointer
attach_function :MagickGetImageHeight, [:pointer], :size_t
attach_function :MagickGetImageWidth, [:pointer], :size_t
attach_function :MagickPingImage, [:pointer, :string], :bool
attach_function :MagickWandGenesis, [], :void
attach_function :NewMagickWand, [], :pointer
end
lib = :ffi
rescue LoadError
# Missing ffi, MagickWand lib, or function in lib.
end
end
 
case lib
handle = FakeImgLib.openimage("path/to/image")</lang>
when :rmagick
# Returns [width, height] of an image file.
def size(path)
img = Magick::Image.ping(path).first
[img.columns, img.rows]
end
when :ffi
F.MagickWandGenesis()
def size(path)
wand = F.NewMagickWand()
F.MagickPingImage(wand, path) or fail 'problem reading image'
[F.MagickGetImageWidth(wand), F.MagickGetImageHeight(wand)]
ensure
F.DestroyMagickWand(wand) if wand
end
else
PngSignature = "\x89PNG\r\n\x1A\n".force_encoding('binary')
def size(path)
File.open(path, 'rb') do |file|
# Only works with PNG: https://www.w3.org/TR/PNG/
# Reads [width, height] from IDHR chunk.
# Checks height != nil, but doesn't check CRC of chunk.
sig, width, height = file.read(24).unpack('a8@16NN')
sig == PngSignature and height or fail 'not a PNG image'
[width, height]
end
end
end
 
# Show the size of each image in ARGV.
status = true
ARGV.empty? and (warn "usage: $0 file..."; exit false)
ARGV.each do |path|
begin
r, c = size(path)
puts "#{path}: #{r}x#{c}"
rescue
status = false
puts "#{path}: #$!"
end
end
exit status</lang>
 
=={{header|Rust}}==
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.