diff options
author | Jacopo Mondi <jacopo.mondi@ideasonboard.com> | 2025-02-21 18:18:37 +0100 |
---|---|---|
committer | Jacopo Mondi <jacopo.mondi@ideasonboard.com> | 2025-02-25 18:53:14 +0100 |
commit | 354697b74facba52a97b745d7f485e29d636b712 (patch) | |
tree | f52d0983654e9c92165700f051ea45947ed5782b | |
parent | f9485f14891c61a06af53eb314b73d1a1c9b09c1 (diff) |
And here we are, this is rustjmondi/c-abi
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
-rw-r--r-- | src/rust/Cargo.toml | 7 | ||||
-rw-r--r-- | src/rust/build.rs | 19 | ||||
-rw-r--r-- | src/rust/src/main.rs | 165 | ||||
-rw-r--r-- | src/rust/wrapper.h | 3 |
4 files changed, 194 insertions, 0 deletions
diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml new file mode 100644 index 00000000..e45d616f --- /dev/null +++ b/src/rust/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "rust" +version = "0.1.0" +edition = "2021" + +[build-dependencies] +bindgen = "*"
\ No newline at end of file diff --git a/src/rust/build.rs b/src/rust/build.rs new file mode 100644 index 00000000..8bc6fb16 --- /dev/null +++ b/src/rust/build.rs @@ -0,0 +1,19 @@ +extern crate bindgen; + +use std::env; +use std::path::PathBuf; + +fn main() { + println!("cargo:rustc-link-lib=libcamera_c"); + println!("cargo::rustc-link-search=/home/jmondi/project/libcamera/worktrees/c-abi/build/src/libcamera_c/"); + + let bindings = bindgen::Builder::default() + .header("wrapper.h") + .generate() + .expect("Unable to generate bindings"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); +}
\ No newline at end of file diff --git a/src/rust/src/main.rs b/src/rust/src/main.rs new file mode 100644 index 00000000..a520336f --- /dev/null +++ b/src/rust/src/main.rs @@ -0,0 +1,165 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +use std::sync::Arc; +use std::vec; +use std::ffi::CStr; +use std::ffi::CString; + +include!(concat!(env!("OUT_DIR"),"/bindings.rs")); + +pub struct Request { + ptr: *mut request, +} + +impl Drop for Request { + fn drop(&mut self) { + unsafe { request_drop(self.ptr) } + } +} + +pub struct CameraConfiguration { + ptr: *mut camera_configuration_t, +} + +impl Drop for CameraConfiguration { + fn drop(&mut self) { + unsafe { camera_drop_configuration(self.ptr) } + } +} + +pub struct Camera { + ptr: *mut camera_t, +} + +impl Camera { + pub fn id(&self) -> Result<String, std::str::Utf8Error> { + unsafe { + /* Return an owning String with a copy of the camera id */ + let cid = camera_id(self.ptr); + let cstr = CStr::from_ptr(cid); + Ok(cstr.to_string_lossy().into_owned()) + } + } + + pub fn acquire(&self) { + unsafe { camera_acquire(self.ptr) } + } + + pub fn release(&self) { + unsafe { camera_release(self.ptr) } + } + + pub fn generateConfiguration(&self, roles: &Vec<u32>) -> CameraConfiguration { + + unsafe { + CameraConfiguration { + ptr: camera_generate_configuration(self.ptr, roles.as_ptr(), roles.len()) + } + } + } + + pub fn configure(&self, config: &CameraConfiguration) { + unsafe { camera_configure(self.ptr, config.ptr) } + } + + pub fn createRequest(&self) -> Request { + unsafe { + Request { + ptr: camera_create_request(self.ptr), + } + } + } +} + +impl Drop for Camera { + fn drop(&mut self) { + unsafe { camera_drop(self.ptr); } + } + +} + +pub struct CameraManager { + ptr: *mut camera_manager, +} + +impl CameraManager { + pub fn new() -> Self { + unsafe { + CameraManager { + ptr: cm_create(), + } + } + } + + pub fn start(&self) { + unsafe { cm_start(self.ptr); } + } + + pub fn stop(&self) { + unsafe { cm_stop(self.ptr); } + } + + pub fn cameras(&self) -> Vec<Arc<Camera>> { + unsafe { + let mut num_cameras : usize = 0; + let vec = cm_list_cameras(self.ptr, &mut num_cameras as *mut usize); + let mut rVec = Vec::with_capacity(num_cameras); + + for i in 0..num_cameras { + rVec.push(Arc::new(Camera { + ptr: cm_camera_list_at(vec, i), + })) + } + + rVec + } + } + + pub fn get(&self, id: &str) -> Camera { + unsafe { + let cstring = CString::new(id).unwrap(); + Camera { + ptr: cm_get_camera(self.ptr, cstring.as_ptr()), + } + } + } + + pub fn put(&self, camera: Camera) { + unsafe { + cm_put_camera(camera.ptr); + } + } +} + +impl Drop for CameraManager { + fn drop(&mut self) { + unsafe { cm_stop(self.ptr); } + } +} + +fn main() { + let manager = CameraManager::new(); + manager.start(); + + let mut camera_name = String::new(); + + let cameras = manager.cameras(); + for camera in cameras { + println!("{}", camera.id().unwrap()); + camera_name = camera.id().unwrap(); + } + + let camera = manager.get(&camera_name); + println!("Got a camera {}", camera_name); + + camera.acquire(); + + let roles = vec![stream_roles_VIDEO_RECORDING]; + let config = camera.generateConfiguration(&roles); + + camera.configure(&config); + + camera.release(); +} diff --git a/src/rust/wrapper.h b/src/rust/wrapper.h new file mode 100644 index 00000000..1747542b --- /dev/null +++ b/src/rust/wrapper.h @@ -0,0 +1,3 @@ +#include "../../include/libcamera_c/camera_manager_c.h" +#include "../../include/libcamera_c/camera_c.h" +#include "../../include/libcamera_c/request_c.h" |