diff --git a/Cargo.toml b/Cargo.toml index 432fceb..05b89bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pihash" -version = "0.4.0" +version = "0.4.1" authors = ["Drew Short "] description = "A simple library for generating perceptual hashes for images and comparing images based on their perceptual hashes." repository = "https://github.com/warricksothr/Perceptual-Image-Hashing/" diff --git a/FFI-tests/ffi_test.py b/FFI-tests/ffi_test.py index 050c24a..8fa353a 100755 --- a/FFI-tests/ffi_test.py +++ b/FFI-tests/ffi_test.py @@ -39,6 +39,13 @@ if os.name == 'nt': lib = CDLL(path) else: lib = cdll.LoadLibrary("libpihash.so") + + +class PIHashes(Structure): + _fields_ = [ + ("ahash", c_ulonglong), + ("dhash", c_ulonglong), + ("phash", c_ulonglong)] # Setting the ctypes return type references for the foreign functions @@ -51,6 +58,9 @@ lib.ext_get_dhash.restype = c_ulonglong lib.ext_get_dhash.argtypes = [c_void_p, c_char_p] lib.ext_get_phash.restype = c_ulonglong lib.ext_get_phash.argtypes = [c_void_p, c_char_p] +lib.ext_get_phashes.restype = c_void_p +lib.ext_get_phashes.argtypes = [c_void_p, c_char_p] +lib.ext_free_phashes.argtypes = [c_void_p] # Takes a pointer and frees the struct at that memory location lib.ext_free.argtypes = [c_void_p] @@ -64,10 +74,16 @@ lib_struct = lib.ext_init("./.hash_cache".encode(encoding="utf-8")) #print('\\x'+'\\x'.join('{:02x}'.format(x) for x in large_image_path)) for image in test_images: - print("Requesting hashes for: %s"% image) - print("ahash: %i"% unsigned64(lib.ext_get_ahash(lib_struct, image))) - print("dhash: %i"% unsigned64(lib.ext_get_dhash(lib_struct, image))) - print("phash: %i"% unsigned64(lib.ext_get_phash(lib_struct, image))) + print("Requesting hashes for: %s"% image) + phashes = lib.ext_get_phashes(lib_struct, image) + pihashes = PIHashes.from_address(phashes) + lib.ext_free_phashes(phashes) + print("ahash: %i"% unsigned64(pihashes.ahash)) + print("dhash: %i"% unsigned64(pihashes.dhash)) + print("phash: %i"% unsigned64(pihashes.phash)) + # print("ahash: %i"% unsigned64(lib.ext_get_ahash(lib_struct, image))) + # print("dhash: %i"% unsigned64(lib.ext_get_dhash(lib_struct, image))) + # print("phash: %i"% unsigned64(lib.ext_get_phash(lib_struct, image))) # Do cleanup # Makes sure that the heap is cleaned up diff --git a/ffi/pihash.h b/ffi/pihash.h index ac8f5e4..1b6828b 100644 --- a/ffi/pihash.h +++ b/ffi/pihash.h @@ -4,4 +4,5 @@ void *ext_init(const char *); void ext_free(); uint64_t ext_get_ahash(void *, const char *); uint64_t ext_get_dhash(void *, const char *); -uint64_t ext_get_phash(void *, const char *); \ No newline at end of file +uint64_t ext_get_phash(void *, const char *); +void *ext_get_phashes(void *, const char *); \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 1982706..d0b028c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,7 +56,9 @@ impl<'a> PIHash<'a> { } pub fn get_phashes(&self, path: &'a Path) -> hash::PerceptualHashes { - hash::get_perceptual_hashes(path, &hash::Precision::Medium, &self.cache) + hash::get_perceptual_hashes(&path, + &hash::Precision::Medium, + &self.cache) } @@ -128,7 +130,7 @@ pub extern "C" fn ext_get_ahash(lib: &PIHash, path_char: *const libc::c_char) -> } }; let path = Path::new(&image_path); - lib.get_ahash(&path) + lib.get_ahash(path) } } @@ -146,7 +148,7 @@ pub extern "C" fn ext_get_dhash(lib: &PIHash, path_char: *const libc::c_char) -> } }; let path = Path::new(&image_path); - lib.get_dhash(&path) + lib.get_dhash(path) } } @@ -164,10 +166,48 @@ pub extern "C" fn ext_get_phash(lib: &PIHash, path_char: *const libc::c_char) -> } }; let path = Path::new(&image_path); - lib.get_phash(&path) + lib.get_phash(path) } } +#[repr(C)] +pub struct PIHashes { + ahash: libc::uint64_t, + dhash: libc::uint64_t, + phash: libc::uint64_t +} + +#[no_mangle] +pub extern "C" fn ext_get_phashes(lib: &PIHash, path_char: *const libc::c_char) -> * mut PIHashes { + unsafe { + let path_str = CStr::from_ptr(path_char); + let image_path = match path_str.to_str() { + Ok(result) => result, + Err(e) => { + println!("Error: {}. Unable to parse '{}'", + e, + to_hex_string(path_str.to_bytes())); + panic!("Unable to parse path") + } + }; + let path = Path::new(&image_path); + let phashes = lib.get_phashes(path); + Box::into_raw(Box::new(PIHashes { + ahash: phashes.ahash, + dhash: phashes.dhash, + phash: phashes.phash + })) + } +} + +#[no_mangle] +pub extern "C" fn ext_free_phashes(raw_phashes: *const libc::c_void) { + unsafe { + drop(Box::from_raw(raw_phashes as *mut PIHashes)); + } +} + + fn to_hex_string(bytes: &[u8]) -> String { println!("length: {}", bytes.len()); let mut strs: Vec = Vec::new();