diff --git a/CHANGELOG b/CHANGELOG index 29f2523..1c61931 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,6 @@ UNRELEASED * Add support for g_error_free to prevent memory leaks of GErrors. - * Explicitly check for minimum v0.10 of gexiv2 system library. + * Explicitly check for minimum v0.16 of gexiv2 system library. * Add support for gexiv2_shutdown(), to be called from main thread. * Update minimum supported Rust version (MSRV) to 1.92 due to dependency reqs. diff --git a/Cargo.toml b/Cargo.toml index 3d0c697..b592fca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,7 @@ bitflags = { version = "1.3", optional = true} [build-dependencies] pkg-config = "0.3" +cc = "1.0" [dev-dependencies] tempfile = "3.3" diff --git a/build.rs b/build.rs index 81c0c1b..cb6f27e 100644 --- a/build.rs +++ b/build.rs @@ -15,13 +15,16 @@ //! Confirm gexiv2 library exists on the system. +extern crate cc; + fn main() { + let mut cfg = cc::Build::new(); let system_library = pkg_config::Config::new() - .atleast_version("0.10") - .probe("gexiv2") + .atleast_version("0.16") + .probe("gexiv2-0.16") .unwrap_or_else(|e| { eprintln!( - "\nThe gexiv2 library was not found by pkg-config/pkgconf on your system.\n\n\ + "\nThe gexiv2 library (at least version 0.16) was not found by pkg-config/pkgconf on your system.\n\n\ Consult the README.md file for suggestions on how to acquire it." ); panic!("{}", e); @@ -50,5 +53,12 @@ fn main() { if (major, minor) >= (milestone_major, milestone_minor) { println!("cargo:rustc-cfg={}", flag); } + }; + cfg.file("src/glue.cpp"); + + for path in system_library.include_paths { + cfg.include(path); } + + cfg.compile("gexiv2_sys_glue"); } diff --git a/examples/preview_properties.rs b/examples/preview_properties.rs index 6bc934a..fccf5ef 100644 --- a/examples/preview_properties.rs +++ b/examples/preview_properties.rs @@ -9,10 +9,8 @@ extern crate libc; use std::ffi; use std::ptr; - static FILE_PATH: &str = "/YOUR/FILE/PATH/GOES/HERE.jpg"; - fn get_file_metadata(path: &str) -> *mut gexiv2::GExiv2Metadata { let mut err: *mut gexiv2::GError = ptr::null_mut(); let c_str_path = ffi::CString::new(path.as_bytes()).unwrap(); @@ -26,7 +24,6 @@ fn get_file_metadata(path: &str) -> *mut gexiv2::GExiv2Metadata { } } - fn main() { unsafe { let meta = get_file_metadata(FILE_PATH); @@ -39,9 +36,10 @@ fn main() { let mut cur_offset = 0; while !(*all_preview_props.offset(cur_offset)).is_null() { let preview_prop = *all_preview_props.offset(cur_offset); - let mime_type = ffi::CStr::from_ptr( - gexiv2::gexiv2_preview_properties_get_mime_type(preview_prop) - ).to_str(); + let mime_type = ffi::CStr::from_ptr(gexiv2::gexiv2_preview_properties_get_mime_type( + preview_prop, + )) + .to_str(); println!("{:?}", mime_type); cur_offset += 1; } diff --git a/examples/raw_tag_access.rs b/examples/raw_tag_access.rs index 8f39bd7..8dd7d27 100644 --- a/examples/raw_tag_access.rs +++ b/examples/raw_tag_access.rs @@ -12,18 +12,22 @@ mod example { extern crate libc; use std::ffi; + use std::ptr; use std::slice; use std::str; + use gexiv2_sys::GError; + pub fn example() { unsafe { let metadata = crate::open_buf::make_new_metadata(); + let mut err: *mut GError = ptr::null_mut(); let tag = ffi::CString::new("Exif.Image.ImageDescription").unwrap(); let tag_value = ffi::CString::new("Raw Tag Access Example").unwrap(); - gexiv2::gexiv2_metadata_set_tag_string(metadata, tag.as_ptr(), tag_value.as_ptr()); + gexiv2::gexiv2_metadata_set_tag_string(metadata, tag.as_ptr(), tag_value.as_ptr(), &mut err); - let raw_tag_struct = gexiv2::gexiv2_metadata_get_tag_raw(metadata, tag.as_ptr()); + let raw_tag_struct = gexiv2::gexiv2_metadata_get_tag_raw(metadata, tag.as_ptr(), &mut err); let mut raw_tag_buffer_size: usize = 0; let raw_tag_buffer = diff --git a/examples/xmp_packet_access.rs b/examples/xmp_packet_access.rs index 941fcbc..5b33a6d 100644 --- a/examples/xmp_packet_access.rs +++ b/examples/xmp_packet_access.rs @@ -10,23 +10,27 @@ mod example { extern crate gexiv2_sys as gexiv2; extern crate libc; - use std::ffi; + use std::{ffi, ptr}; + + use gexiv2_sys::GError; pub fn example() { unsafe { let metadata = crate::open_buf::make_new_metadata(); + let mut err: *mut GError = ptr::null_mut(); let tag = ffi::CString::new("Xmp.dc.title").unwrap(); let tag_value = ffi::CString::new("Example").unwrap(); - gexiv2::gexiv2_metadata_set_tag_string(metadata, tag.as_ptr(), tag_value.as_ptr()); + gexiv2::gexiv2_metadata_set_tag_string(metadata, tag.as_ptr(), tag_value.as_ptr(), &mut err); gexiv2::gexiv2_metadata_generate_xmp_packet( metadata, (gexiv2::GExiv2XmpFormatFlags::OMIT_PACKET_WRAPPER - | gexiv2::GExiv2XmpFormatFlags::OMIT_ALL_FORMATTING).bits(), + | gexiv2::GExiv2XmpFormatFlags::OMIT_ALL_FORMATTING) + .bits(), 1, ); - let packet = gexiv2::gexiv2_metadata_get_xmp_packet(metadata); + let packet = gexiv2::gexiv2_metadata_get_xmp_packet(metadata, &mut err); println!("{}", ffi::CStr::from_ptr(packet).to_str().unwrap()); gexiv2::gexiv2_metadata_free(metadata); diff --git a/src/glue.cpp b/src/glue.cpp new file mode 100644 index 0000000..f4daa19 --- /dev/null +++ b/src/glue.cpp @@ -0,0 +1,22 @@ +#include +#include + +extern "C" { + +#ifndef gexiv2_metadata_free + void gexiv2_metadata_free (GExiv2Metadata *self) { + g_return_if_fail(GEXIV2_IS_METADATA(self)); + + g_object_unref(self); + } +#endif + +#ifndef gexiv2_preview_image_free + void gexiv2_preview_image_free(GExiv2PreviewImage *self) { + g_return_if_fail(GEXIV2_IS_PREVIEW_IMAGE(self)); + + g_object_unref(self); + } +#endif + +} diff --git a/src/lib.rs b/src/lib.rs index da979aa..389715d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,8 +114,8 @@ extern "C" { pub fn gexiv2_metadata_get_pixel_height(this: *mut GExiv2Metadata) -> c_int; // Tag management. - pub fn gexiv2_metadata_has_tag(this: *mut GExiv2Metadata, tag: *const c_char) -> c_int; - pub fn gexiv2_metadata_clear_tag(this: *mut GExiv2Metadata, tag: *const c_char) -> c_int; + pub fn gexiv2_metadata_has_tag(this: *mut GExiv2Metadata, tag: *const c_char, error: *mut *mut GError) -> c_int; + pub fn gexiv2_metadata_clear_tag(this: *mut GExiv2Metadata, tag: *const c_char, error: *mut *mut GError) -> c_int; pub fn gexiv2_metadata_clear(this: *mut GExiv2Metadata); pub fn gexiv2_metadata_has_exif(this: *mut GExiv2Metadata) -> c_int; pub fn gexiv2_metadata_clear_exif(this: *mut GExiv2Metadata); @@ -128,75 +128,200 @@ extern "C" { pub fn gexiv2_metadata_get_iptc_tags(this: *mut GExiv2Metadata) -> *mut *mut c_char; // Tag data getters/setters. - pub fn gexiv2_metadata_get_tag_string(this: *mut GExiv2Metadata, tag: *const c_char) -> *const c_char; - pub fn gexiv2_metadata_set_tag_string(this: *mut GExiv2Metadata, tag: *const c_char, value: *const c_char) -> c_int; - pub fn gexiv2_metadata_get_tag_interpreted_string(this: *mut GExiv2Metadata, tag: *const c_char) -> *const c_char; - pub fn gexiv2_metadata_get_tag_multiple(this: *mut GExiv2Metadata, tag: *const c_char) -> *mut *mut c_char; - pub fn gexiv2_metadata_set_tag_multiple(this: *mut GExiv2Metadata, tag: *const c_char, values: *mut *const c_char) -> c_int; - pub fn gexiv2_metadata_get_tag_long(this: *mut GExiv2Metadata, tag: *const c_char) -> c_long; - pub fn gexiv2_metadata_set_tag_long(this: *mut GExiv2Metadata, tag: *const c_char, value: c_long) -> c_int; - pub fn gexiv2_metadata_get_exif_tag_rational(this: *mut GExiv2Metadata, tag: *const c_char, nom: *mut c_int, den: *mut c_int) -> c_int; - pub fn gexiv2_metadata_set_exif_tag_rational(this: *mut GExiv2Metadata, tag: *const c_char, nom: c_int, den: c_int) -> c_int; + pub fn gexiv2_metadata_get_tag_string( + this: *mut GExiv2Metadata, + tag: *const c_char, + error: *mut *mut GError, + ) -> *const c_char; + pub fn gexiv2_metadata_set_tag_string( + this: *mut GExiv2Metadata, + tag: *const c_char, + value: *const c_char, + error: *mut *mut GError, + ) -> c_int; + pub fn gexiv2_metadata_get_tag_interpreted_string( + this: *mut GExiv2Metadata, + tag: *const c_char, + error: *mut *mut GError, + ) -> *const c_char; + pub fn gexiv2_metadata_get_tag_multiple( + this: *mut GExiv2Metadata, + tag: *const c_char, + error: *mut *mut GError, + ) -> *mut *mut c_char; + pub fn gexiv2_metadata_set_tag_multiple( + this: *mut GExiv2Metadata, + tag: *const c_char, + values: *mut *const c_char, + error: *mut *mut GError, + ) -> c_int; + pub fn gexiv2_metadata_get_tag_long( + this: *mut GExiv2Metadata, + tag: *const c_char, + error: *mut *mut GError, + ) -> c_long; + pub fn gexiv2_metadata_set_tag_long( + this: *mut GExiv2Metadata, + tag: *const c_char, + value: c_long, + error: *mut *mut GError, + ) -> c_int; + pub fn gexiv2_metadata_get_exif_tag_rational( + this: *mut GExiv2Metadata, + tag: *const c_char, + nom: *mut c_int, + den: *mut c_int, + error: *mut *mut GError, + ) -> c_int; + pub fn gexiv2_metadata_set_exif_tag_rational( + this: *mut GExiv2Metadata, + tag: *const c_char, + nom: c_int, + den: c_int, + error: *mut *mut GError, + ) -> c_int; // Helper & convenience getters/setters. - pub fn gexiv2_metadata_get_orientation(this: *mut GExiv2Metadata) -> Orientation; - pub fn gexiv2_metadata_set_orientation(this: *mut GExiv2Metadata, orientation: Orientation); - pub fn gexiv2_metadata_get_metadata_pixel_width(this: *mut GExiv2Metadata) -> c_int; - pub fn gexiv2_metadata_get_metadata_pixel_height(this: *mut GExiv2Metadata) -> c_int; - pub fn gexiv2_metadata_set_metadata_pixel_width(this: *mut GExiv2Metadata, width: c_int); - pub fn gexiv2_metadata_set_metadata_pixel_height(this: *mut GExiv2Metadata, height: c_int); - pub fn gexiv2_metadata_get_exposure_time(this: *mut GExiv2Metadata, nom: *mut c_int, den: *mut c_int) -> c_int; - pub fn gexiv2_metadata_get_fnumber(this: *mut GExiv2Metadata) -> c_double; - pub fn gexiv2_metadata_get_focal_length(this: *mut GExiv2Metadata) -> c_double; - pub fn gexiv2_metadata_get_iso_speed(this: *mut GExiv2Metadata) -> c_int; - pub fn gexiv2_metadata_get_comment(this: *mut GExiv2Metadata) -> *const c_char; - pub fn gexiv2_metadata_set_comment(this: *mut GExiv2Metadata, comment: *const c_char); + pub fn gexiv2_metadata_get_orientation(this: *mut GExiv2Metadata, error: *mut *mut GError) -> Orientation; + pub fn gexiv2_metadata_set_orientation(this: *mut GExiv2Metadata, orientation: Orientation, error: *mut *mut GError); + pub fn gexiv2_metadata_get_metadata_pixel_width( + this: *mut GExiv2Metadata, + error: *mut *mut GError, + ) -> c_int; + pub fn gexiv2_metadata_get_metadata_pixel_height( + this: *mut GExiv2Metadata, + error: *mut *mut GError, + ) -> c_int; + pub fn gexiv2_metadata_set_metadata_pixel_width( + this: *mut GExiv2Metadata, + width: c_int, + error: *mut *mut GError, + ); + pub fn gexiv2_metadata_set_metadata_pixel_height( + this: *mut GExiv2Metadata, + height: c_int, + error: *mut *mut GError, + ); + pub fn gexiv2_metadata_get_exposure_time( + this: *mut GExiv2Metadata, + nom: *mut c_int, + den: *mut c_int, + error: *mut *mut GError, + ) -> c_int; + pub fn gexiv2_metadata_get_fnumber(this: *mut GExiv2Metadata, error: *mut *mut GError) -> c_double; + pub fn gexiv2_metadata_get_focal_length(this: *mut GExiv2Metadata, error: *mut *mut GError) -> c_double; + pub fn gexiv2_metadata_get_iso_speed(this: *mut GExiv2Metadata, error: *mut *mut GError) -> c_int; + pub fn gexiv2_metadata_get_comment(this: *mut GExiv2Metadata, error: *mut *mut GError) -> *const c_char; + pub fn gexiv2_metadata_set_comment(this: *mut GExiv2Metadata, comment: *const c_char, error: *mut *mut GError); pub fn gexiv2_metadata_clear_comment(this: *mut GExiv2Metadata); // GPS-related functions. - pub fn gexiv2_metadata_get_gps_longitude(this: *mut GExiv2Metadata, longitude: *mut c_double) -> c_int; - pub fn gexiv2_metadata_get_gps_latitude(this: *mut GExiv2Metadata, latitude: *mut c_double) -> c_int; - pub fn gexiv2_metadata_get_gps_altitude(this: *mut GExiv2Metadata, altitude: *mut c_double) -> c_int; - pub fn gexiv2_metadata_get_gps_info(this: *mut GExiv2Metadata, longitude: *mut c_double, latitude: *mut c_double, altitude: *mut c_double) -> c_int; - pub fn gexiv2_metadata_set_gps_info(this: *mut GExiv2Metadata, longitude: c_double, latitude: c_double, altitude: c_double) -> c_int; - pub fn gexiv2_metadata_delete_gps_info(this: *mut GExiv2Metadata); + pub fn gexiv2_metadata_get_gps_longitude( + this: *mut GExiv2Metadata, + error: *mut *mut GError, + ) -> c_double; + pub fn gexiv2_metadata_get_gps_latitude( + this: *mut GExiv2Metadata, + error: *mut *mut GError, + ) -> c_double; + pub fn gexiv2_metadata_get_gps_altitude( + this: *mut GExiv2Metadata, + error: *mut *mut GError, + ) -> c_double; + pub fn gexiv2_metadata_get_gps_info( + this: *mut GExiv2Metadata, + longitude: *mut c_double, + latitude: *mut c_double, + altitude: *mut c_double, + error: *mut *mut GError, + ) -> c_int; + pub fn gexiv2_metadata_set_gps_info( + this: *mut GExiv2Metadata, + longitude: c_double, + latitude: c_double, + altitude: c_double, + error: *mut *mut GError, + ) -> c_int; + pub fn gexiv2_metadata_delete_gps_info(this: *mut GExiv2Metadata, error: *mut *mut GError); // Tag information functions. pub fn gexiv2_metadata_is_exif_tag(tag: *const c_char) -> c_int; pub fn gexiv2_metadata_is_iptc_tag(tag: *const c_char) -> c_int; pub fn gexiv2_metadata_is_xmp_tag(tag: *const c_char) -> c_int; - pub fn gexiv2_metadata_get_tag_label(tag: *const c_char) -> *const c_char; - pub fn gexiv2_metadata_get_tag_description(tag: *const c_char) -> *const c_char; - pub fn gexiv2_metadata_get_tag_type(tag: *const c_char) -> *const c_char; + pub fn gexiv2_metadata_get_tag_label( + tag: *const c_char, + error: *mut *mut GError, + ) -> *const c_char; + pub fn gexiv2_metadata_get_tag_description( + tag: *const c_char, + error: *mut *mut GError, + ) -> *const c_char; + pub fn gexiv2_metadata_get_tag_type( + tag: *const c_char, + error: *mut *mut GError, + ) -> *const c_char; // Exif thumbnail getter/setters. - pub fn gexiv2_metadata_get_exif_thumbnail(this: *mut GExiv2Metadata, buffer: *mut *mut u8, size: *mut c_int) -> c_int; - pub fn gexiv2_metadata_set_exif_thumbnail_from_file(this: *mut GExiv2Metadata, path: *const c_char, error: *mut *mut GError) -> c_int; - pub fn gexiv2_metadata_set_exif_thumbnail_from_buffer(this: *mut GExiv2Metadata, buffer: *const u8, size: c_int); - pub fn gexiv2_metadata_erase_exif_thumbnail(this: *mut GExiv2Metadata); + pub fn gexiv2_metadata_get_exif_thumbnail( + this: *mut GExiv2Metadata, + buffer: *mut *mut u8, + size: *mut c_int, + ) -> c_int; + pub fn gexiv2_metadata_set_exif_thumbnail_from_file( + this: *mut GExiv2Metadata, + path: *const c_char, + error: *mut *mut GError, + ) -> c_int; + pub fn gexiv2_metadata_set_exif_thumbnail_from_buffer( + this: *mut GExiv2Metadata, + buffer: *const u8, + size: c_int, + error: *mut *mut GError, + ); + pub fn gexiv2_metadata_erase_exif_thumbnail(this: *mut GExiv2Metadata, error: *mut *mut GError); // Preview image properties. - pub fn gexiv2_metadata_get_preview_properties(this: *mut GExiv2Metadata) -> *mut *mut GExiv2PreviewProperties; - pub fn gexiv2_preview_properties_get_mime_type(this: *mut GExiv2PreviewProperties) -> *const c_char; - pub fn gexiv2_preview_properties_get_extension(this: *mut GExiv2PreviewProperties) -> *const c_char; + pub fn gexiv2_metadata_get_preview_properties( + this: *mut GExiv2Metadata, + ) -> *mut *mut GExiv2PreviewProperties; + pub fn gexiv2_preview_properties_get_mime_type( + this: *mut GExiv2PreviewProperties, + ) -> *const c_char; + pub fn gexiv2_preview_properties_get_extension( + this: *mut GExiv2PreviewProperties, + ) -> *const c_char; pub fn gexiv2_preview_properties_get_size(this: *mut GExiv2PreviewProperties) -> c_uint; pub fn gexiv2_preview_properties_get_width(this: *mut GExiv2PreviewProperties) -> c_uint; pub fn gexiv2_preview_properties_get_height(this: *mut GExiv2PreviewProperties) -> c_uint; // Preview images. - pub fn gexiv2_metadata_get_preview_image(this: *mut GExiv2Metadata, props: *mut GExiv2PreviewProperties) -> *mut GExiv2PreviewImage; + pub fn gexiv2_metadata_get_preview_image( + this: *mut GExiv2Metadata, + props: *mut GExiv2PreviewProperties, + error: *mut *mut GError, + ) -> *mut GExiv2PreviewImage; pub fn gexiv2_preview_image_free(this: *mut GExiv2PreviewImage); - pub fn gexiv2_preview_image_get_data(this: *mut GExiv2PreviewImage, size: *mut c_uint) -> *const c_uchar; + pub fn gexiv2_preview_image_get_data( + this: *mut GExiv2PreviewImage, + size: *mut c_uint, + ) -> *const c_uchar; pub fn gexiv2_preview_image_get_mime_type(this: *mut GExiv2PreviewImage) -> *const c_char; pub fn gexiv2_preview_image_get_extension(this: *mut GExiv2PreviewImage) -> *const c_char; pub fn gexiv2_preview_image_get_width(this: *mut GExiv2PreviewImage) -> c_uint; pub fn gexiv2_preview_image_get_height(this: *mut GExiv2PreviewImage) -> c_uint; - pub fn gexiv2_preview_image_write_file(this: *mut GExiv2PreviewImage, path: *const c_char) -> c_long; + pub fn gexiv2_preview_image_write_file( + this: *mut GExiv2PreviewImage, + path: *const c_char, + ) -> c_long; // XMP namespace management. - pub fn gexiv2_metadata_register_xmp_namespace(name: *const c_char, prefix: *const c_char) -> c_int; - pub fn gexiv2_metadata_unregister_xmp_namespace(name: *const c_char) -> c_int; - pub fn gexiv2_metadata_unregister_all_xmp_namespaces(); + pub fn gexiv2_metadata_register_xmp_namespace( + name: *const c_char, + prefix: *const c_char, + error: *mut *mut GError, + ) -> c_int; + pub fn gexiv2_metadata_unregister_xmp_namespace(name: *const c_char, error: *mut *mut GError) -> c_int; + pub fn gexiv2_metadata_unregister_all_xmp_namespaces(error: *mut *mut GError); // Logging. pub fn gexiv2_log_get_default_handler() -> GExiv2LogHandler; @@ -207,13 +332,15 @@ extern "C" { pub fn gexiv2_log_use_glib_logging(); } - #[cfg(feature = "raw-tag-access")] extern "C" { - pub fn gexiv2_metadata_get_tag_raw(this: *mut GExiv2Metadata, tag: *const libc::c_char) -> *mut glib::GBytes; + pub fn gexiv2_metadata_get_tag_raw( + this: *mut GExiv2Metadata, + tag: *const libc::c_char, + error: *mut *mut GError, + ) -> *mut glib::GBytes; } - #[cfg(feature = "xmp-packet-access")] #[macro_use] extern crate bitflags; @@ -233,10 +360,13 @@ bitflags! { #[cfg(feature = "xmp-packet-access")] extern "C" { - pub fn gexiv2_metadata_generate_xmp_packet(this: *mut GExiv2Metadata, xmp_format_flags: libc::c_ulong, padding: u32) -> *const c_char; - pub fn gexiv2_metadata_get_xmp_packet(this: *mut GExiv2Metadata) -> *const c_char; + pub fn gexiv2_metadata_generate_xmp_packet( + this: *mut GExiv2Metadata, + xmp_format_flags: libc::c_ulong, + padding: u32, + ) -> *const c_char; + pub fn gexiv2_metadata_get_xmp_packet(this: *mut GExiv2Metadata, error: *mut *mut GError) -> *const c_char; } - #[cfg(test)] mod test; diff --git a/src/test.rs b/src/test.rs index 6515936..92f7a64 100644 --- a/src/test.rs +++ b/src/test.rs @@ -26,7 +26,6 @@ use std::slice; use super::*; - static MINI_JPEG: &[u8] = &[ 255, 216, 255, 219, 00, 43, 00, 03, 02, 02, 02, 02, 02, 03, 02, 02, 02, 03, 03, 03, 03, 04, 06, 04, 04, 04, 04, 04, 08, 06, 06, 05, 06, 09, 08, 10, 10, 09, 08, 09, 09, 10, 12, 15, 12, 10, 11, @@ -55,6 +54,16 @@ unsafe fn make_new_metadata() -> *mut GExiv2Metadata { metadata } +struct Finalizer { + cleanup: F, +} + +impl Drop for Finalizer { + fn drop(&mut self) { + println!("Drop"); + (self.cleanup)(); + } +} #[test] fn initialize() { @@ -70,13 +79,15 @@ fn get_version() { } } - // Image information. #[test] fn metadata_get_supports_exif() { unsafe { let meta = make_new_metadata(); + let _finalizer = Finalizer { + cleanup: || gexiv2_metadata_free(meta), + }; assert_eq!(gexiv2_metadata_get_supports_exif(meta), 1); } } @@ -85,6 +96,9 @@ fn metadata_get_supports_exif() { fn metadata_get_supports_iptc() { unsafe { let meta = make_new_metadata(); + let _finalizer = Finalizer { + cleanup: || gexiv2_metadata_free(meta), + }; assert_eq!(gexiv2_metadata_get_supports_iptc(meta), 1); } } @@ -93,6 +107,9 @@ fn metadata_get_supports_iptc() { fn metadata_get_supports_xmp() { unsafe { let meta = make_new_metadata(); + let _finalizer = Finalizer { + cleanup: || gexiv2_metadata_free(meta), + }; assert_eq!(gexiv2_metadata_get_supports_xmp(meta), 1); } } @@ -101,6 +118,9 @@ fn metadata_get_supports_xmp() { fn metadata_get_mime_type() { unsafe { let meta = make_new_metadata(); + let _finalizer = Finalizer { + cleanup: || gexiv2_metadata_free(meta), + }; let result = gexiv2_metadata_get_mime_type(meta); let result = ffi::CStr::from_ptr(result).to_str().unwrap(); assert_eq!(result, "image/jpeg"); @@ -111,6 +131,9 @@ fn metadata_get_mime_type() { fn metadata_get_pixel_width() { unsafe { let meta = make_new_metadata(); + let _finalizer = Finalizer { + cleanup: || gexiv2_metadata_free(meta), + }; assert_eq!(gexiv2_metadata_get_pixel_width(meta), 1); } } @@ -119,23 +142,30 @@ fn metadata_get_pixel_width() { fn metadata_get_pixel_height() { unsafe { let meta = make_new_metadata(); + let _finalizer = Finalizer { + cleanup: || gexiv2_metadata_free(meta), + }; assert_eq!(gexiv2_metadata_get_pixel_height(meta), 1); } } - // Helper & convenience getters/setters. #[test] fn metadata_set_and_get_metadata_pixel_width() { unsafe { let meta = make_new_metadata(); - gexiv2_metadata_set_metadata_pixel_width(meta, 2); - assert_eq!(gexiv2_metadata_get_metadata_pixel_width(meta), 2); + let _finalizer = Finalizer { + cleanup: || gexiv2_metadata_free(meta), + }; + gexiv2_metadata_set_metadata_pixel_width(meta, 2, ptr::null_mut()); + assert_eq!( + gexiv2_metadata_get_metadata_pixel_width(meta, ptr::null_mut()), + 2 + ); } } - // Tag information functions. #[test] @@ -172,7 +202,7 @@ fn metadata_is_xmp_tag() { fn metadata_get_tag_label() { unsafe { let tag = ffi::CString::new("Exif.Image.ImageDescription").unwrap(); - let result = gexiv2_metadata_get_tag_label(tag.as_ptr()); + let result = gexiv2_metadata_get_tag_label(tag.as_ptr(), ptr::null_mut()); let result = ffi::CStr::from_ptr(result).to_str().unwrap(); assert_eq!(result, "Image Description"); } @@ -182,7 +212,7 @@ fn metadata_get_tag_label() { fn metadata_get_tag_description() { unsafe { let tag = ffi::CString::new("Exif.Image.FillOrder").unwrap(); - let result = gexiv2_metadata_get_tag_description(tag.as_ptr()); + let result = gexiv2_metadata_get_tag_description(tag.as_ptr(), ptr::null_mut()); let result = ffi::CStr::from_ptr(result).to_str().unwrap(); assert_eq!(result, "The logical order of bits within a byte"); } @@ -192,19 +222,22 @@ fn metadata_get_tag_description() { fn metadata_get_tag_type() { unsafe { let tag = ffi::CString::new("Exif.Image.ImageDescription").unwrap(); - let result = gexiv2_metadata_get_tag_type(tag.as_ptr()); + let result = gexiv2_metadata_get_tag_type(tag.as_ptr(), ptr::null_mut()); let result = ffi::CStr::from_ptr(result).to_str().unwrap(); assert_eq!(result, "Ascii"); } } - // Exif thumbnail getter/setters. #[test] fn metadata_get_and_set_exif_thumbnail_from_buffer() { unsafe { let meta = make_new_metadata(); + let mut err: *mut GError = ptr::null_mut(); + let _finalizer = Finalizer { + cleanup: || gexiv2_metadata_free(meta), + }; let mut thumb: *mut u8 = ptr::null_mut(); let mut thumb_size: libc::c_int = 0; assert_eq!(gexiv2_metadata_get_exif_thumbnail(meta, &mut thumb, &mut thumb_size), 1); @@ -213,6 +246,11 @@ fn metadata_get_and_set_exif_thumbnail_from_buffer() { meta, MINI_JPEG.as_ptr(), MINI_JPEG.len() as libc::c_int, + &mut err, + ); + assert_eq!( + gexiv2_metadata_get_exif_thumbnail(meta, &mut thumb, &mut thumb_size), + 1 ); assert_eq!(gexiv2_metadata_get_exif_thumbnail(meta, &mut thumb, &mut thumb_size), 1); assert!(!thumb.is_null()); @@ -224,6 +262,9 @@ fn metadata_get_and_set_exif_thumbnail_from_buffer() { fn metadata_set_exif_thumbnail_from_file() { unsafe { let meta = make_new_metadata(); + let _finalizer = Finalizer { + cleanup: || gexiv2_metadata_free(meta), + }; let tmp_dir = tempfile::tempdir().unwrap(); let tmp_file_path = tmp_dir.path().join("thumb.jpg"); @@ -250,22 +291,26 @@ fn metadata_set_exif_thumbnail_from_file() { fn metadata_erase_exif_thumbnail() { unsafe { let meta = make_new_metadata(); + let mut err: *mut GError = ptr::null_mut(); + let _finalizer = Finalizer { + cleanup: || gexiv2_metadata_free(meta), + }; let mut thumb: *mut u8 = ptr::null_mut(); let mut thumb_size: libc::c_int = 0; gexiv2_metadata_set_exif_thumbnail_from_buffer( meta, MINI_JPEG.as_ptr(), MINI_JPEG.len() as libc::c_int, + &mut err, ); assert_eq!(gexiv2_metadata_get_exif_thumbnail(meta, &mut thumb, &mut thumb_size), 1); assert!(!thumb.is_null()); - gexiv2_metadata_erase_exif_thumbnail(meta); + gexiv2_metadata_erase_exif_thumbnail(meta, &mut err); assert_eq!(gexiv2_metadata_get_exif_thumbnail(meta, &mut thumb, &mut thumb_size), 1); assert!(thumb.is_null()); } } - // Logging. #[test]