diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 034c9da..07a937c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,113 +3,77 @@ on: push: tags: - "[0-9]*.[0-9]*.[0-9]*" + - "v[0-9]*.[0-9]*.[0-9]*" jobs: - build_gem: + build_source_gem: name: Build source gem runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: ruby/setup-ruby-pkgs@v1 + - uses: actions/checkout@v6.0.2 + - uses: ruby/setup-ruby@v1 with: ruby-version: 3.4 - - run: sudo apt-get update && sudo apt-get install -y libopencv-dev libvips - - run: gem update --system - - run: rake gem + bundler-cache: true + - run: bundle exec rake build - name: Upload source gem - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7.0.0 with: - name: libfacedetection.gem + name: source-gem path: pkg/*.gem retention-days: 1 - compile_native_gems: - name: Compile native gem - needs: build_gem + build_native_gems: + name: Build native gem (${{ matrix.platform }}) + runs-on: ubuntu-latest strategy: + fail-fast: false matrix: - include: - - os: ubuntu-24.04 - platform: x86_64-linux - ruby: "3.4" - - os: ubuntu-24.04-arm - platform: aarch64-linux - ruby: "3.4" - - os: macos-latest - platform: arm64-darwin - ruby: "3.4" - runs-on: ${{ matrix.os }} + platform: + - x86_64-linux + - aarch64-linux + - x86_64-darwin + - arm64-darwin steps: - - uses: actions/checkout@v4 - - - uses: ruby/setup-ruby-pkgs@v1 - with: - ruby-version: ${{ matrix.ruby }} - - - name: Install system dependencies on Linux - if: matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-latest-arm64' - run: sudo apt-get update && sudo apt-get install -y libopencv-dev libvips - - - name: Install system dependencies on macOS - if: matrix.os == 'macos-latest' - run: brew install opencv vips - - - name: Install gem-compiler - run: gem install gem-compiler - - - name: Download source gem - uses: actions/download-artifact@v4 + - uses: actions/checkout@v6.0.2 + - uses: ruby/setup-ruby@v1 with: - name: libfacedetection.gem - path: pkg/ - - - name: Compile gem - run: | - SOURCE_GEM=$(ls pkg/*.gem | grep -v -- '-x86_64-linux\|aarch64-linux\|arm64-darwin') - gem compile $SOURCE_GEM --prune - - - name: Upload compiled gem - uses: actions/upload-artifact@v4 + ruby-version: 3.4 + bundler-cache: true + - name: Build native gems + run: bundle exec rb-sys-dock --platform ${{ matrix.platform }} --build + - name: Upload native gems + uses: actions/upload-artifact@v7.0.0 with: - name: libfacedetection-${{ matrix.platform }}.gem - path: ./*.gem + name: native-gem-${{ matrix.platform }} + path: pkg/*-${{ matrix.platform }}.gem retention-days: 1 release: name: Create GitHub Release - needs: compile_native_gems + needs: + - build_source_gem + - build_native_gems runs-on: ubuntu-latest + permissions: + contents: write steps: - - uses: actions/checkout@v4 - - name: Extract version id: extract_version run: | VERSION=${GITHUB_REF#refs/tags/} - echo "GEM_VERSION=$VERSION" >> $GITHUB_ENV + VERSION=${VERSION#v} + echo "GEM_VERSION=$VERSION" >> "$GITHUB_ENV" - name: Download all artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8.0.1 with: path: artifacts - - name: Rename gem files with version - run: | - mkdir -p release_gems - for gem in artifacts/libfacedetection-*.gem/*.gem; do - platform=$(basename $gem | sed -E 's/libfacedetection-([^-]+-[^-]+)\.gem/\1/') - - # Construct the target filename: NAME-VERSION-PLATFORM.gem - target_filename="libfacedetection-${GEM_VERSION}-${platform}.gem" - target_path="release_gems/$target_filename" - mv "$gem" "$target_path" - done - # Move source gem to release_gems directory - mv artifacts/libfacedetection.gem/*.gem release_gems/libfacedetection-${GEM_VERSION}.gem - - name: Create release uses: softprops/action-gh-release@v2 with: - tag_name: ${{ env.GEM_VERSION }} - files: release_gems/*.gem + tag_name: ${{ github.ref_name }} + name: libfacedetection ${{ env.GEM_VERSION }} + files: artifacts/**/*.gem generate_release_notes: true diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index d0b074a..cba857a 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -1,53 +1,31 @@ name: run-tests -on: [push] + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + jobs: - build_gem: - name: Build and test ruby extension - runs-on: ubuntu-latest + ruby_extension: + name: Ruby ${{ matrix.ruby }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + ruby: ["3.2", "3.3", "3.4", "4.0"] steps: - - uses: actions/checkout@v3 - - uses: ruby/setup-ruby-pkgs@v1 + - uses: actions/checkout@v6.0.2 + - uses: ruby/setup-ruby@v1 with: - ruby-version: 3.4 - - run: sudo apt-get update && sudo apt-get install -y libopencv-dev libvips - - run: gem update --system - - run: rake gem - - run: gem install $(ls -1 pkg/*.gem) - - run: bundle install - - run: ruby tests/test_detection.rb - # compile_native_gem: - # name: Compile native gem - # runs-on: ubuntu-latest - # strategy: - # matrix: - # platform: - # - x86_64-linux - # - x86_64-darwin - # - arm64-darwin - # - aarch64-linux - # steps: - # - uses: actions/checkout@v2 - - # - uses: ruby/setup-ruby@v1 - # with: - # ruby-version: '3.1' - # bundler-cache: true - - # - uses: oxidize-rb/cross-gem-action@main - # with: - # platform: ${{ matrix.platform }} - # setup: | # optional - # env - # bundle install - # env: | # optional - # RUBY_CC_VERSION=3.1.0:3.0.0:2.7.0 - # CXX_aarch64_unknown_linux_gnu= - - # - uses: actions/download-artifact@v3 - # with: - # name: cross-gem - # path: pkg/ - - # - name: Display structure of built gems - # run: ls -R - # working-directory: pkg/ + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - uses: actions-rust-lang/setup-rust-toolchain@v1 + - name: Install libvips on Linux + if: runner.os == 'Linux' + run: sudo apt-get update && sudo apt-get install -y libvips + - name: Install libvips on macOS + if: runner.os == 'macOS' + run: brew install vips + - run: bundle exec rake test diff --git a/Cargo.lock b/Cargo.lock index b0e5866..a0d69da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -265,23 +265,23 @@ checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libfacedetection" -version = "0.1.0" -source = "git+https://github.com/fetlife/libfacedetection-rs.git?rev=7426f33ba101514932a5ef58456761735c7bf3dc#7426f33ba101514932a5ef58456761735c7bf3dc" -dependencies = [ - "libfacedetection-sys", - "thiserror", -] - -[[package]] -name = "libfacedetection-ruby" version = "0.0.1" dependencies = [ - "libfacedetection", + "libfacedetection 0.1.0", "magnus", "opencv", "rb-sys", ] +[[package]] +name = "libfacedetection" +version = "0.1.0" +source = "git+https://github.com/fetlife/libfacedetection-rs.git?rev=7426f33ba101514932a5ef58456761735c7bf3dc#7426f33ba101514932a5ef58456761735c7bf3dc" +dependencies = [ + "libfacedetection-sys", + "thiserror", +] + [[package]] name = "libfacedetection-sys" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index 719949e..8460d84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,20 @@ -[workspace] -members = ["ext/*"] -resolver = "2" +[package] +name = "libfacedetection" +version = "0.0.1" +edition = "2021" +publish = false +authors = ["Fetlife "] + +[lib] +name = "libfacedetection" +crate-type = ["cdylib"] + +[dependencies] +libfacedetection_rs = { package = "libfacedetection", git = "https://github.com/fetlife/libfacedetection-rs.git", optional = true, rev = "7426f33ba101514932a5ef58456761735c7bf3dc" } +opencv = { version = "0.88.6", optional = true, features = ["clang-runtime"] } +magnus = { version = "0.8.2" } +rb-sys = { version = "0.9.126", default-features = false, features = ["stable-api-compiled-fallback"] } + +[features] +default = ["libfacedetection"] +libfacedetection = ["dep:libfacedetection_rs"] diff --git a/Readme.md b/README.md similarity index 96% rename from Readme.md rename to README.md index 0093a7b..53aa907 100644 --- a/Readme.md +++ b/README.md @@ -10,6 +10,7 @@ This gem is automatically released using Github Releases when a new version tag 2. Compiling native extensions for multiple platforms: - x86_64-linux (Ubuntu 24.04) - aarch64-linux (Ubuntu 24.04 ARM) + - x86_64-darwin (macOS) - arm64-darwin (macOS) To create a new release: @@ -22,4 +23,3 @@ To create a new release: ``` You can find all releases on the [GitHub Releases page](https://github.com/fetlife/facedetection-ruby/releases). - diff --git a/Rakefile b/Rakefile index a20b0b6..836b342 100644 --- a/Rakefile +++ b/Rakefile @@ -1,29 +1,21 @@ -require 'rubygems/package_task' +# frozen_string_literal: true -spec = eval(File.read("libfacedetection.gemspec")) -GEM_RUBY_VERSION = "3.4.0" -DOCKER_IMAGE = "ruby:#{GEM_RUBY_VERSION}-bullseye" +require "bundler/gem_tasks" +require "rake/testtask" +require "rb_sys/extensiontask" -def compile_cmd(_arch) - "gem instal gem-compiler; curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y; source '/root/.cargo/env'; rake gem:native" -end - -gem_task = Gem::PackageTask.new(spec) do |pkg| - pkg.need_zip = true - pkg.need_tar = true -end +GEMSPEC = Gem::Specification.load("libfacedetection.gemspec") -desc "Generate a pre-compiled native gem for #{RUBY_PLATFORM}" -task "gem:native" => ["gem"] do - sh "gem compile #{gem_task.package_dir_path}.gem" -end +task default: :test +task gem: :build -desc "Generate a pre-compiled native gem for aarch64-linux" -task "gem:native:aarch64-linux" => ["gem"] do - sh %{docker run --rm --platform linux/arm64 -v $(pwd):/src -w /src #{DOCKER_IMAGE} /bin/bash -c "#{compile_cmd('aarch64-unknown-linux-musl')}"} +RbSys::ExtensionTask.new("libfacedetection", GEMSPEC) do |ext| + ext.lib_dir = "lib/libfacedetection" end -desc "Generate a pre-compiled native gem for x86_64-linux" -task "gem:native:x86_64-linux" => ["gem"] do - sh %{docker run --rm --platform linux/amd64 -v $(pwd):/src -w /src #{DOCKER_IMAGE} /bin/bash -c "#{compile_cmd('x86_64-unknown-linux-musl')}"} +Rake::TestTask.new do |t| + t.deps << "compile:dev" + t.libs << "lib" + t.libs << "tests" + t.test_files = FileList["tests/test_*.rb"] end diff --git a/ext/libfacedetection/Cargo.toml b/ext/libfacedetection/Cargo.toml deleted file mode 100644 index 814777a..0000000 --- a/ext/libfacedetection/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "libfacedetection-ruby" -version = "0.0.1" -edition = "2021" -publish = false -authors = ["Fetlife "] - -[lib] -name = "libfacedetection_ruby" -crate-type = ["cdylib"] - -[dependencies] -libfacedetection = { git = "https://github.com/fetlife/libfacedetection-rs.git", optional = true, rev = "7426f33ba101514932a5ef58456761735c7bf3dc" } -opencv = { version = "0.88.6", optional = true, features = ["clang-runtime"] } -magnus = { version = "0.8.2" } -rb-sys = { version = "0.9.126", default-features = false, features = ["stable-api-compiled-fallback"] } - -[features] -default = ["libfacedetection"] diff --git a/ext/libfacedetection/extconf.rb b/ext/libfacedetection/extconf.rb index a4f2855..e0c7e9b 100644 --- a/ext/libfacedetection/extconf.rb +++ b/ext/libfacedetection/extconf.rb @@ -1,4 +1,3 @@ -require "mkmf" -require "rb_sys/mkmf" +# frozen_string_literal: true -create_rust_makefile("libfacedetection/libfacedetection_ruby") +load File.expand_path("../../extconf.rb", __dir__) diff --git a/extconf.rb b/extconf.rb new file mode 100644 index 0000000..ca688da --- /dev/null +++ b/extconf.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require "mkmf" +require "pathname" +require "rb_sys/mkmf" + +create_rust_makefile("libfacedetection") do |config| + relative_ext_dir = Pathname(__dir__).relative_path_from(Pathname.pwd) + # rb_sys strips one leading "./" while constructing the Cargo manifest path. + config.ext_dir = "./#{relative_ext_dir}" + config.profile = ENV.fetch("RB_SYS_CARGO_PROFILE", "release").to_sym +end diff --git a/lib/libfacedetection.rb b/lib/libfacedetection.rb index 9ffe5f3..2fa1823 100644 --- a/lib/libfacedetection.rb +++ b/lib/libfacedetection.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "libfacedetection/version" module Libfacedetection @@ -12,22 +14,26 @@ def available? end end -begin - [ - "libfacedetection/#{Libfacedetection::RUBY_API_VERSION}/libfacedetection_ruby", - "libfacedetection/libfacedetection_ruby", - "../ext/libfacedetection/libfacedetection_ruby" - ].each do |path| - begin - require_relative path - Libfacedetection.instance_variable_set(:@available, true) - break - rescue LoadError - next - end - end +[ + "libfacedetection/#{Libfacedetection::RUBY_API_VERSION}/libfacedetection", + "libfacedetection/libfacedetection", + "../ext/libfacedetection/libfacedetection", +].each do |path| + require_relative path + Libfacedetection.instance_variable_set(:@available, true) + break rescue LoadError - Libfacedetection.instance_variable_set(:@available, false) + next +end + +unless Libfacedetection.available? + begin + extension_dir = Gem.loaded_specs["libfacedetection"]&.extension_dir if defined?(Gem) + require File.join(extension_dir, "libfacedetection") if extension_dir + Libfacedetection.instance_variable_set(:@available, true) + rescue LoadError + nil + end end Libfacedetection.instance_variable_set(:@available, false) unless Libfacedetection.available? diff --git a/lib/libfacedetection/version.rb b/lib/libfacedetection/version.rb index bea9de5..df49c74 100644 --- a/lib/libfacedetection/version.rb +++ b/lib/libfacedetection/version.rb @@ -1,3 +1,3 @@ module Libfacedetection - VERSION = "0.4.0".freeze + VERSION = "0.4.1".freeze end diff --git a/libfacedetection.gemspec b/libfacedetection.gemspec index 8f90adc..715a8d4 100644 --- a/libfacedetection.gemspec +++ b/libfacedetection.gemspec @@ -19,11 +19,13 @@ Gem::Specification.new do |spec| spec.files = Dir[ "Cargo.toml", + "Cargo.lock", "lib/**/*.rb", "ext/**/*", + "extconf.rb", + "src/**/*.rs", "*.gemspec", "README.md", - "LICENSE.txt" ].reject do |path| path.match?(%r{\A(?:lib/libfacedetection/(?:.*\.(?:bundle|so|dll|dylib))|ext/libfacedetection/(?:Makefile|mkmf\.log|target/|.*\.(?:bundle|so|dll)))}) end @@ -31,14 +33,15 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] spec.extensions = ["ext/libfacedetection/extconf.rb"] - spec.add_dependency "rb_sys", "~> 0.9.126" + spec.add_dependency "rb_sys", "~> 0.9" spec.add_development_dependency "rake", "~> 13.0" spec.add_development_dependency "rake-compiler", "~> 1.2" + spec.add_development_dependency "minitest", "~> 5.0" spec.add_development_dependency "ruby-vips" spec.add_development_dependency "ffi" spec.metadata = { "github_repo" => "ssh://github.com/fetlife/facedetection-ruby", - "cargo_crate_name" => "libfacedetection-ruby" + "cargo_crate_name" => "libfacedetection" } end diff --git a/ext/libfacedetection/src/lib.rs b/src/lib.rs similarity index 54% rename from ext/libfacedetection/src/lib.rs rename to src/lib.rs index 5c9552e..d28a700 100644 --- a/ext/libfacedetection/src/lib.rs +++ b/src/lib.rs @@ -1,22 +1,22 @@ -use magnus::{error::Result, exception, Error, Integer, RArray, RHash, Symbol}; +use magnus::{error::Result, Error, RArray, Ruby}; #[cfg(feature = "opencv")] -fn detect_opencv(content: Vec) -> Result { +fn detect_opencv(ruby: &Ruby, content: Vec) -> Result { use opencv::{core::Size, imgcodecs, imgproc, objdetect, prelude::*, types}; let cascade_file_path = opencv::core::find_file("haarcascades/haarcascade_frontalface_alt.xml", true, false) - .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?; + .map_err(|e| Error::new(ruby.exception_runtime_error(), e.to_string()))?; let mut classifier = objdetect::CascadeClassifier::new(&cascade_file_path).map_err(|e| { Error::new( - exception::runtime_error(), + ruby.exception_runtime_error(), format!("failed creating classifier: {}", e), ) })?; let img = imgcodecs::imdecode(&types::VectorOfu8::from(content), imgproc::COLOR_BGR2GRAY) .map_err(|e| { Error::new( - exception::runtime_error(), + ruby.exception_runtime_error(), format!("failed decoding image: {}", e), ) })?; @@ -33,39 +33,45 @@ fn detect_opencv(content: Vec) -> Result { ) .map_err(|e| { Error::new( - exception::runtime_error(), + ruby.exception_runtime_error(), format!("Failed to run detect_multi_scale: {}", e), ) })?; - let result = RArray::new(); + let result = ruby.ary_new(); for face in faces { - let hash = RHash::new(); - // let landmarks = RArray::new(); - hash.aset(Symbol::new("x"), Integer::from_i64(face.x as i64))?; - hash.aset(Symbol::new("y"), Integer::from_i64(face.y as i64))?; - hash.aset(Symbol::new("width"), Integer::from_i64(face.width as i64))?; - hash.aset(Symbol::new("height"), Integer::from_i64(face.height as i64))?; + let hash = ruby.hash_new(); + hash.aset(ruby.to_symbol("x"), ruby.integer_from_i64(face.x as i64))?; + hash.aset(ruby.to_symbol("y"), ruby.integer_from_i64(face.y as i64))?; + hash.aset( + ruby.to_symbol("width"), + ruby.integer_from_i64(face.width as i64), + )?; + hash.aset( + ruby.to_symbol("height"), + ruby.integer_from_i64(face.height as i64), + )?; result.push(hash)?; } Ok(result) } #[cfg(all(feature = "libfacedetection", feature = "opencv"))] -fn detect_libfacedetection(content: Vec) -> Result { +fn detect_libfacedetection(ruby: &Ruby, content: Vec) -> Result { use opencv::{imgcodecs, prelude::*, types}; let img = imgcodecs::imdecode(&types::VectorOfu8::from(content), imgcodecs::IMREAD_COLOR) .map_err(|e| { Error::new( - exception::runtime_error(), + ruby.exception_runtime_error(), format!("unable to decode image: {}", e), ) })?; detect_libfacedetection_data( + ruby, img.ptr(0).map_err(|e| { Error::new( - exception::runtime_error(), + ruby.exception_runtime_error(), format!("unable to read image data: {}", e), ) })?, @@ -76,29 +82,30 @@ fn detect_libfacedetection(content: Vec) -> Result { } #[cfg(not(feature = "opencv"))] -fn detect_opencv(_content: Vec) -> Result { +fn detect_opencv(ruby: &Ruby, _content: Vec) -> Result { Err(Error::new( - exception::runtime_error(), + ruby.exception_runtime_error(), "OpenCV is not enabled", )) } #[cfg(not(all(feature = "libfacedetection", feature = "opencv")))] -fn detect_libfacedetection(_content: Vec) -> Result { +fn detect_libfacedetection(ruby: &Ruby, _content: Vec) -> Result { Err(Error::new( - exception::runtime_error(), + ruby.exception_runtime_error(), "need to have both libfacedetection and OpenCV enabled", )) } #[cfg(feature = "libfacedetection")] fn detect_libfacedetection_data( + ruby: &Ruby, bgrdata: *const u8, width: i32, height: i32, step: Option, ) -> Result { - let facedetect_result = libfacedetection::facedetect_cnn( + let facedetect_result = libfacedetection_rs::facedetect_cnn( bgrdata, width, height, @@ -106,65 +113,78 @@ fn detect_libfacedetection_data( ) .map_err(|e| { Error::new( - exception::runtime_error(), + ruby.exception_runtime_error(), format!("libfacedetection error: {}", e), ) })?; - let result = RArray::new(); + let result = ruby.ary_new(); for face in facedetect_result.faces { - let hash = RHash::new(); - let landmarks = RArray::new(); - hash.aset(Symbol::new("x"), Integer::from_i64(face.x as i64))?; - hash.aset(Symbol::new("y"), Integer::from_i64(face.y as i64))?; - hash.aset(Symbol::new("width"), Integer::from_i64(face.width as i64))?; - hash.aset(Symbol::new("height"), Integer::from_i64(face.height as i64))?; + let hash = ruby.hash_new(); + let landmarks = ruby.ary_new(); + hash.aset(ruby.to_symbol("x"), ruby.integer_from_i64(face.x as i64))?; + hash.aset(ruby.to_symbol("y"), ruby.integer_from_i64(face.y as i64))?; + hash.aset( + ruby.to_symbol("width"), + ruby.integer_from_i64(face.width as i64), + )?; + hash.aset( + ruby.to_symbol("height"), + ruby.integer_from_i64(face.height as i64), + )?; hash.aset( - Symbol::new("confidence"), - Integer::from_i64(face.confidence as i64), + ruby.to_symbol("confidence"), + ruby.integer_from_i64(face.confidence as i64), )?; for landmark in face.landmarks { - let a = RArray::new(); - a.push(Integer::from_i64(landmark.0 as i64))?; - a.push(Integer::from_i64(landmark.1 as i64))?; + let a = ruby.ary_new(); + a.push(ruby.integer_from_i64(landmark.0 as i64))?; + a.push(ruby.integer_from_i64(landmark.1 as i64))?; landmarks.push(a)?; } - hash.aset(Symbol::new("landmarks"), landmarks)?; + hash.aset(ruby.to_symbol("landmarks"), landmarks)?; result.push(hash)?; } Ok(result) } -fn pub_detect_opencv(content: String) -> Result { - detect_opencv(content.into_bytes()) +fn pub_detect_opencv(ruby: &Ruby, content: String) -> Result { + detect_opencv(ruby, content.into_bytes()) } -fn pub_detect_libfacedetection(content: String) -> Result { - detect_libfacedetection(content.into_bytes()) +fn pub_detect_libfacedetection(ruby: &Ruby, content: String) -> Result { + detect_libfacedetection(ruby, content.into_bytes()) } fn pub_detect_libfacedetection_image_data( + ruby: &Ruby, data_ptr: usize, width: usize, height: usize, ) -> Result { - detect_libfacedetection_data(data_ptr as *const u8, width as i32, height as i32, None) + detect_libfacedetection_data( + ruby, + data_ptr as *const u8, + width as i32, + height as i32, + None, + ) } -fn features() -> Result { - let result = RArray::new(); +fn features(ruby: &Ruby) -> Result { + let result = ruby.ary_new(); #[cfg(feature = "libfacedetection")] { - result.push(magnus::Symbol::new("libfacedetection"))?; + result.push(ruby.to_symbol("libfacedetection"))?; } #[cfg(feature = "opencv")] { - result.push(magnus::Symbol::new("opencv"))?; + result.push(ruby.to_symbol("opencv"))?; } Ok(result) } #[magnus::init] -fn init(ruby: &magnus::Ruby) -> Result<()> { +fn init(ruby: &Ruby) -> Result<()> { let module = ruby.define_module("Libfacedetection")?; module.define_module_function("detect_opencv", magnus::function!(pub_detect_opencv, 1))?; module.define_module_function(