aboutsummaryrefslogtreecommitdiff
path: root/core/bindings/c_lang/src
diff options
context:
space:
mode:
author1992414357@qq.com <1992414357@qq.com>2025-06-13 22:33:53 +0800
committer1992414357@qq.com <1992414357@qq.com>2025-06-13 22:33:53 +0800
commit22ccd970a4ea47edd39abe8662805d8137083253 (patch)
tree2561d7131c57a632de0943437c7b6fa739eb8321 /core/bindings/c_lang/src
parent83c6fc2d55cdd7de949f2815b86dfe0b9cc18f27 (diff)
.
Diffstat (limited to 'core/bindings/c_lang/src')
-rw-r--r--core/bindings/c_lang/src/data/mod.rs1
-rw-r--r--core/bindings/c_lang/src/data/ngpd_player.rs139
-rw-r--r--core/bindings/c_lang/src/lib.rs1
3 files changed, 141 insertions, 0 deletions
diff --git a/core/bindings/c_lang/src/data/mod.rs b/core/bindings/c_lang/src/data/mod.rs
new file mode 100644
index 0000000..32af6d8
--- /dev/null
+++ b/core/bindings/c_lang/src/data/mod.rs
@@ -0,0 +1 @@
+pub mod ngpd_player; \ No newline at end of file
diff --git a/core/bindings/c_lang/src/data/ngpd_player.rs b/core/bindings/c_lang/src/data/ngpd_player.rs
new file mode 100644
index 0000000..2ab615c
--- /dev/null
+++ b/core/bindings/c_lang/src/data/ngpd_player.rs
@@ -0,0 +1,139 @@
+use std::ffi::{CStr, CString};
+use std::os::raw::{c_char, c_double, c_int};
+use std::ptr;
+use nogamepads_core::data::player::player_data::{Account, Customize, Player};
+
+#[repr(C)]
+pub struct FfiAccount {
+ id: *mut c_char,
+ player_hash: *mut c_char,
+}
+
+#[repr(C)]
+pub struct FfiCustomize {
+ nickname: *mut c_char,
+ color_hue: c_int,
+ color_saturation: c_double,
+ color_value: c_double,
+}
+
+#[repr(C)]
+pub struct FfiPlayer {
+ account: FfiAccount,
+ customize: *mut FfiCustomize,
+}
+
+impl From<Account> for FfiAccount {
+ fn from(acc: Account) -> Self {
+ FfiAccount {
+ id: CString::new(acc.id).unwrap().into_raw(),
+ player_hash: CString::new(acc.player_hash).unwrap().into_raw(),
+ }
+ }
+}
+
+impl From<Player> for FfiPlayer {
+ fn from(player: Player) -> Self {
+ let account = FfiAccount::from(player.account);
+ let customize = player.customize.map(|c| {
+ Box::into_raw(Box::new(FfiCustomize {
+ nickname: CString::new(c.nickname).unwrap().into_raw(),
+ color_hue: c.color_hue,
+ color_saturation: c.color_saturation,
+ color_value: c.color_value,
+ }))
+ }).unwrap_or(ptr::null_mut());
+
+ FfiPlayer { account, customize }
+ }
+}
+
+impl TryFrom<&FfiPlayer> for Player {
+ type Error = ();
+
+ fn try_from(ffi: &FfiPlayer) -> Result<Self, Self::Error> {
+ let account = Account {
+ id: unsafe { CStr::from_ptr(ffi.account.id) }.to_str().map_err(|_| ())?.to_owned(),
+ player_hash: unsafe { CStr::from_ptr(ffi.account.player_hash) }.to_str().map_err(|_| ())?.to_owned(),
+ };
+
+ let customize = if !ffi.customize.is_null() {
+ let c = unsafe { &*ffi.customize };
+ Some(Customize {
+ nickname: unsafe { CStr::from_ptr(c.nickname) }.to_str().map_err(|_| ())?.to_owned(),
+ color_hue: c.color_hue,
+ color_saturation: c.color_saturation,
+ color_value: c.color_value,
+ })
+ } else {
+ None
+ };
+
+ Ok(Player { account, customize })
+ }
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn player_register(id: *const c_char, password: *const c_char) -> *mut FfiPlayer {
+ let id_str = unsafe { CStr::from_ptr(id) }.to_string_lossy();
+ let pass_str = unsafe { CStr::from_ptr(password) }.to_string_lossy();
+
+ let player = Player::register(id_str.into_owned(), pass_str.into_owned());
+ Box::into_raw(Box::new(FfiPlayer::from(player)))
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn player_check(player: *const FfiPlayer, password: *const c_char) -> bool {
+ let player = unsafe { &*player };
+ let pass_str = unsafe { CStr::from_ptr(password) }.to_string_lossy();
+
+ Player::try_from(player)
+ .map(|p| p.check(pass_str.into_owned()))
+ .unwrap_or(false)
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn player_set_nickname(player: *mut FfiPlayer, nickname: *const c_char) {
+ let nickname_str = unsafe { CStr::from_ptr(nickname) }.to_string_lossy().into_owned();
+ let mut rust_player : Player = unsafe { (&*player).try_into().unwrap() };
+
+ rust_player.nickname(&nickname_str);
+ *unsafe { &mut *player } = FfiPlayer::from(rust_player);
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn player_set_hue(player: *mut FfiPlayer, hue: c_int) {
+ let mut rust_player : Player = unsafe { (&*player).try_into().unwrap() };
+
+ rust_player.hue(hue);
+ *unsafe { &mut *player } = FfiPlayer::from(rust_player);
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn player_set_hsv(
+ player: *mut FfiPlayer, hue: c_int, saturation: c_double, value: c_double
+) {
+ let mut rust_player : Player = unsafe { (&*player).try_into().unwrap() };
+
+ rust_player.hsv(hue, saturation, value);
+ *unsafe { &mut *player } = FfiPlayer::from(rust_player);
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn player_free(player: *mut FfiPlayer) {
+ if player.is_null() { return; }
+
+ let ffi_player = unsafe { Box::from_raw(player) };
+
+ // Free account strings
+ unsafe {
+ let _ = CString::from_raw(ffi_player.account.id);
+ let _ = CString::from_raw(ffi_player.account.player_hash);
+ }
+
+ // Free customize if present
+ if !ffi_player.customize.is_null() {
+ let ffi_custom = unsafe { Box::from_raw(ffi_player.customize) };
+ unsafe { let _ = CString::from_raw(ffi_custom.nickname); };
+ }
+} \ No newline at end of file
diff --git a/core/bindings/c_lang/src/lib.rs b/core/bindings/c_lang/src/lib.rs
new file mode 100644
index 0000000..12e35bb
--- /dev/null
+++ b/core/bindings/c_lang/src/lib.rs
@@ -0,0 +1 @@
+pub mod data; \ No newline at end of file