#![allow(non_snake_case)]
use ATriaPlugin::{ATriaPlugin as InnerATria, ComputeBackend};
use pluma_plugin_trait::PluMAPlugin;
use std::ffi::CStr;
use std::os::raw::c_char;
#[derive(Debug)]
pub struct ATriaGPUPlugin {
inner: InnerATria,
}
impl Default for ATriaGPUPlugin {
fn default() -> Self {
Self {
inner: InnerATria::with_backend(ComputeBackend::Cuda),
}
}
}
impl ATriaGPUPlugin {
pub fn new() -> Self {
Self::default()
}
pub fn inner(&self) -> &InnerATria {
&self.inner
}
}
impl PluMAPlugin for ATriaGPUPlugin {
fn input(&mut self, filepath: String) -> Result<(), Box<dyn std::error::Error>> {
self.inner.input(filepath)
}
fn run(&mut self) -> Result<(), Box<dyn std::error::Error>> {
let effective = self.inner.effective_backend();
if !matches!(effective, ComputeBackend::Cuda) {
log::warn!(
"[ATriaGPU] CUDA was requested but unavailable at runtime; \
falling back to {:?}. If this wasn't your intention, install \
the CUDA toolkit + a working NVIDIA driver and rerun.",
effective
);
}
self.inner.run()
}
fn output(&mut self, filepath: String) -> Result<(), Box<dyn std::error::Error>> {
self.inner.output(filepath)
}
}
#[unsafe(no_mangle)]
pub extern "C" fn ATriaGPU_plugin_create() -> *mut std::ffi::c_void {
Box::into_raw(Box::new(ATriaGPUPlugin::new())) as *mut std::ffi::c_void
}
#[unsafe(no_mangle)]
pub extern "C" fn ATriaGPU_plugin_destroy(ptr: *mut std::ffi::c_void) {
if !ptr.is_null() {
unsafe {
let _ = Box::from_raw(ptr as *mut ATriaGPUPlugin);
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn ATriaGPU_plugin_input(ptr: *mut std::ffi::c_void, filename: *const c_char) {
if ptr.is_null() || filename.is_null() {
eprintln!("[ATriaGPU] Error: null pointer in plugin_input");
return;
}
unsafe {
let plugin = &mut *(ptr as *mut ATriaGPUPlugin);
let filename_str = match CStr::from_ptr(filename).to_str() {
Ok(s) => s.to_string(),
Err(e) => {
eprintln!("[ATriaGPU] Error converting filename: {}", e);
return;
}
};
if let Err(e) = plugin.input(filename_str) {
eprintln!("[ATriaGPU] Error in input: {}", e);
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn ATriaGPU_plugin_run(ptr: *mut std::ffi::c_void) {
if ptr.is_null() {
eprintln!("[ATriaGPU] Error: null pointer in plugin_run");
return;
}
unsafe {
let plugin = &mut *(ptr as *mut ATriaGPUPlugin);
if let Err(e) = plugin.run() {
eprintln!("[ATriaGPU] Error in run: {}", e);
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn ATriaGPU_plugin_output(ptr: *mut std::ffi::c_void, filename: *const c_char) {
if ptr.is_null() || filename.is_null() {
eprintln!("[ATriaGPU] Error: null pointer in plugin_output");
return;
}
unsafe {
let plugin = &mut *(ptr as *mut ATriaGPUPlugin);
let filename_str = match CStr::from_ptr(filename).to_str() {
Ok(s) => s.to_string(),
Err(e) => {
eprintln!("[ATriaGPU] Error converting filename: {}", e);
return;
}
};
if let Err(e) = plugin.output(filename_str) {
eprintln!("[ATriaGPU] Error in output: {}", e);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn constructs_with_cuda_backend() {
let p = ATriaGPUPlugin::new();
let _ = p.inner();
}
#[test]
fn ffi_create_and_destroy_round_trip() {
let ptr = ATriaGPU_plugin_create();
assert!(!ptr.is_null());
ATriaGPU_plugin_destroy(ptr);
}
}