summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacopo Mondi <jacopo.mondi@ideasonboard.com>2025-02-21 18:18:37 +0100
committerJacopo Mondi <jacopo.mondi@ideasonboard.com>2025-02-25 18:53:14 +0100
commit354697b74facba52a97b745d7f485e29d636b712 (patch)
treef52d0983654e9c92165700f051ea45947ed5782b
parentf9485f14891c61a06af53eb314b73d1a1c9b09c1 (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.toml7
-rw-r--r--src/rust/build.rs19
-rw-r--r--src/rust/src/main.rs165
-rw-r--r--src/rust/wrapper.h3
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"