use libxc_ffi::ffi;
use std::ffi::CStr;
unsafe fn cstr_to_string(ptr: *const std::ffi::c_char) -> String {
if ptr.is_null() {
return String::new();
}
CStr::from_ptr(ptr).to_string_lossy().into_owned()
}
unsafe fn cstr_to_string_with_free(ptr: *const std::ffi::c_char) -> String {
let s = cstr_to_string(ptr);
unsafe fn free_ptr(p: *mut std::ffi::c_void) {
#[cfg(all(feature = "cuda", not(feature = "api-v7_1")))]
{
cudarc::runtime::sys::cudaFree(p);
}
#[cfg(any(not(feature = "cuda"), feature = "api-v7_1"))]
{
libc::free(p);
}
}
unsafe { free_ptr(ptr as *mut std::ffi::c_void) };
s
}
pub fn libxc_version() -> (i32, i32, i32) {
let mut major: std::ffi::c_int = 0;
let mut minor: std::ffi::c_int = 0;
let mut micro: std::ffi::c_int = 0;
unsafe {
ffi::xc_version(&mut major, &mut minor, &mut micro);
}
(major as i32, minor as i32, micro as i32)
}
pub fn libxc_version_string() -> String {
unsafe { cstr_to_string(ffi::xc_version_string()) }
}
pub fn libxc_reference() -> String {
unsafe { cstr_to_string(ffi::xc_reference()) }
}
pub fn libxc_reference_doi() -> String {
unsafe { cstr_to_string(ffi::xc_reference_doi()) }
}
pub fn libxc_reference_key() -> String {
unsafe { cstr_to_string(ffi::xc_reference_key()) }
}
pub fn libxc_functional_get_number(name: &str) -> Option<i32> {
let c_name = std::ffi::CString::new(name).ok()?;
let n = unsafe { ffi::xc_functional_get_number(c_name.as_ptr()) };
(n != -1).then_some(n as i32)
}
pub fn libxc_functional_get_name(number: i32) -> Option<String> {
let ptr = unsafe { ffi::xc_functional_get_name(number as std::ffi::c_int) };
if ptr.is_null() {
return None;
}
let s = unsafe { cstr_to_string_with_free(ptr) };
(!s.is_empty()).then_some(s)
}
pub fn libxc_number_of_functionals() -> i32 {
unsafe { ffi::xc_number_of_functionals() as i32 }
}
pub fn libxc_available_functional_numbers() -> Vec<i32> {
let n = libxc_number_of_functionals();
let mut list: Vec<std::ffi::c_int> = vec![0; n as usize];
unsafe {
ffi::xc_available_functional_numbers(list.as_mut_ptr());
}
list.into_iter().collect()
}
pub fn libxc_available_functional_names() -> Vec<String> {
let n = libxc_number_of_functionals();
let mut ids: Vec<std::ffi::c_int> = vec![0; n as usize];
unsafe {
ffi::xc_available_functional_numbers_by_name(ids.as_mut_ptr());
}
ids.into_iter()
.filter_map(|id| {
let ptr = unsafe { ffi::xc_functional_get_name(id) };
if ptr.is_null() {
return None;
}
let s = unsafe { cstr_to_string_with_free(ptr) };
(!s.is_empty()).then_some(s)
})
.collect()
}
pub fn print_library_path() {
#[cfg(feature = "dynamic_loading")]
{
println!("libxc is dynamically loaded from: {:?}", unsafe {
&ffi::dyload_lib().__libraries_path
});
}
#[cfg(not(feature = "dynamic_loading"))]
{
println!("libxc is statically linked, please manually use ldd the binary to check the libxc path.");
}
}