Browse Source

Working on passing structs through the cffi

master
Drew Short 7 years ago
parent
commit
5726b1af3f
  1. 2
      Cargo.toml
  2. 24
      FFI-tests/ffi_test.py
  3. 3
      ffi/pihash.h
  4. 48
      src/lib.rs

2
Cargo.toml

@ -1,6 +1,6 @@
[package] [package]
name = "pihash" name = "pihash"
version = "0.4.0"
version = "0.4.1"
authors = ["Drew Short <warrick@sothr.com>"] authors = ["Drew Short <warrick@sothr.com>"]
description = "A simple library for generating perceptual hashes for images and comparing images based on their perceptual hashes." 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/" repository = "https://github.com/warricksothr/Perceptual-Image-Hashing/"

24
FFI-tests/ffi_test.py

@ -39,6 +39,13 @@ if os.name == 'nt':
lib = CDLL(path) lib = CDLL(path)
else: else:
lib = cdll.LoadLibrary("libpihash.so") 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 # 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_dhash.argtypes = [c_void_p, c_char_p]
lib.ext_get_phash.restype = c_ulonglong lib.ext_get_phash.restype = c_ulonglong
lib.ext_get_phash.argtypes = [c_void_p, c_char_p] 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 # Takes a pointer and frees the struct at that memory location
lib.ext_free.argtypes = [c_void_p] 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)) #print('\\x'+'\\x'.join('{:02x}'.format(x) for x in large_image_path))
for image in test_images: 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 # Do cleanup
# Makes sure that the heap is cleaned up # Makes sure that the heap is cleaned up

3
ffi/pihash.h

@ -4,4 +4,5 @@ void *ext_init(const char *);
void ext_free(); void ext_free();
uint64_t ext_get_ahash(void *, const char *); uint64_t ext_get_ahash(void *, const char *);
uint64_t ext_get_dhash(void *, const char *); uint64_t ext_get_dhash(void *, const char *);
uint64_t ext_get_phash(void *, const char *);
uint64_t ext_get_phash(void *, const char *);
void *ext_get_phashes(void *, const char *);

48
src/lib.rs

@ -56,7 +56,9 @@ impl<'a> PIHash<'a> {
} }
pub fn get_phashes(&self, path: &'a Path) -> hash::PerceptualHashes { 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); 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); 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); 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 { fn to_hex_string(bytes: &[u8]) -> String {
println!("length: {}", bytes.len()); println!("length: {}", bytes.len());
let mut strs: Vec<String> = Vec::new(); let mut strs: Vec<String> = Vec::new();

Loading…
Cancel
Save