diff options
| author | 1992414357@qq.com <1992414357@qq.com> | 2025-05-28 09:08:16 +0800 |
|---|---|---|
| committer | 1992414357@qq.com <1992414357@qq.com> | 2025-05-28 09:08:16 +0800 |
| commit | 11b7b6f05bcf682d1616a74029a4415a05de9fc0 (patch) | |
| tree | 0ab7b9fea645dadf75ef56840e259d56f5e54beb | |
| parent | c470dff02c2c4def065efa59dd04026ca50dc090 (diff) | |
增加 C/C++ 的绑定
| -rw-r--r-- | core_c/build.rs | 33 | ||||
| -rw-r--r-- | core_c/src/data_c/common.rs | 6 | ||||
| -rw-r--r-- | core_c/src/data_c/connection_callback_message_c.rs | 129 | ||||
| -rw-r--r-- | core_c/src/data_c/connection_message_c.rs | 95 | ||||
| -rw-r--r-- | core_c/src/data_c/control_message_c.rs | 150 | ||||
| -rw-r--r-- | core_c/src/data_c/game_message_c.rs | 114 | ||||
| -rw-r--r-- | core_c/src/data_c/game_profile_c.rs | 44 | ||||
| -rw-r--r-- | core_c/src/data_c/mod.rs | 11 | ||||
| -rw-r--r-- | core_c/src/data_c/player_info_c.rs | 33 | ||||
| -rw-r--r-- | core_c/src/data_c/player_info_list_c.rs | 8 | ||||
| -rw-r--r-- | core_c/src/service_c/common.rs | 4 | ||||
| -rw-r--r-- | core_c/src/service_c/mod.rs | 4 | ||||
| -rw-r--r-- | core_c/src/service_c/padclient.rs | 73 | ||||
| -rw-r--r-- | core_c/src/service_c/padserver.rs | 175 |
14 files changed, 879 insertions, 0 deletions
diff --git a/core_c/build.rs b/core_c/build.rs new file mode 100644 index 0000000..1dd893b --- /dev/null +++ b/core_c/build.rs @@ -0,0 +1,33 @@ +use cbindgen::{generate_with_config, Config, Language, ParseConfig, ParseExpandConfig}; +use std::env; + +fn main() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + + let config_c = Config { + language: Language::C, + header: Some("/* NoGamepads C Bindings. */".to_string()), + + parse: ParseConfig { + expand: ParseExpandConfig { + all_features: true, + ..Default::default() + }, + ..Default::default() + }, + ..Config::default() + }; + + let mut config_cpp = config_c.clone(); + config_cpp.language = Language::Cxx; + config_cpp.include_version = true; + config_cpp.header = Some("/* NoGamepads C++ Bindings. */".to_string()); + config_cpp.namespace = Some("nogamepads".to_string()); + + generate_with_config(&crate_dir, config_c) + .expect("Could not generate nogamepads.h") + .write_to_file("../.cargo/shared/target/release/deps/nogamepads.h"); + generate_with_config(&crate_dir, config_cpp) + .expect("Could not generate nogamepads_cpp.h") + .write_to_file("../.cargo/shared/target/release/deps/nogamepads_cpp.h"); +}
\ No newline at end of file diff --git a/core_c/src/data_c/common.rs b/core_c/src/data_c/common.rs new file mode 100644 index 0000000..58c34c4 --- /dev/null +++ b/core_c/src/data_c/common.rs @@ -0,0 +1,6 @@ +#[repr(C)] +#[allow(unused_imports)] +#[derive(Copy, Clone)] +pub struct KeyData { + pub(crate) key: u8 +}
\ No newline at end of file diff --git a/core_c/src/data_c/connection_callback_message_c.rs b/core_c/src/data_c/connection_callback_message_c.rs new file mode 100644 index 0000000..bb96a0d --- /dev/null +++ b/core_c/src/data_c/connection_callback_message_c.rs @@ -0,0 +1,129 @@ +use std::ffi::c_void; +use std::mem::ManuallyDrop; +use std::ptr::null_mut; +use nogamepads_lib_rs::pad_data::game_profile::game_profile::GameProfile; +use nogamepads_lib_rs::pad_data::pad_messages::nogamepads_messages::{ConnectionCallbackMessage, ConnectionErrorType}; + +#[repr(C)] +#[allow(unused_imports)] +pub struct ConnCallbackMsgC { + tag: ConnCallbackMsgCTag, + data: ConnCallbackMsgCUnion, +} + +#[repr(C)] +#[allow(unused_imports)] +pub enum ConnCallbackMsgCTag { + Profile, Deny, Fail, Ok, Welcome, Err +} + +#[repr(C)] +#[allow(unused_imports)] +pub union ConnCallbackMsgCUnion { + nul: *mut c_void, + profile: ManuallyDrop<GameProfile>, + conn_err: ConnErrTypeC +} + +#[repr(C)] +#[allow(unused_imports)] +#[derive(Copy, Clone)] +pub enum ConnErrTypeC { + ContainSamePlayer, PlayerBanned, Timeout, GameLocked, WhatTheHell +} + +impl From<ConnErrTypeC> for ConnectionErrorType { + fn from(value: ConnErrTypeC) -> Self { + match value { + ConnErrTypeC::ContainSamePlayer => { ConnectionErrorType::ContainSamePlayer } + ConnErrTypeC::PlayerBanned => { ConnectionErrorType::PlayerBanned } + ConnErrTypeC::Timeout => { ConnectionErrorType::Timeout } + ConnErrTypeC::GameLocked => { ConnectionErrorType::GameLocked } + ConnErrTypeC::WhatTheHell => { ConnectionErrorType::WhatTheHell } + } + } +} + +impl From<ConnectionErrorType> for ConnErrTypeC { + fn from(value: ConnectionErrorType) -> Self { + match value { + ConnectionErrorType::ContainSamePlayer => { ConnErrTypeC::ContainSamePlayer } + ConnectionErrorType::PlayerBanned => { ConnErrTypeC::PlayerBanned } + ConnectionErrorType::Timeout => { ConnErrTypeC::Timeout } + ConnectionErrorType::GameLocked => { ConnErrTypeC::GameLocked } + ConnectionErrorType::WhatTheHell => { ConnErrTypeC::WhatTheHell } + } + } +} + +impl From<ConnCallbackMsgC> for ConnectionCallbackMessage { + fn from(mut value: ConnCallbackMsgC) -> Self { + match value.tag { + ConnCallbackMsgCTag::Profile => unsafe { + let profile = ManuallyDrop::take(&mut value.data.profile); + ConnectionCallbackMessage::Profile(profile) + } + ConnCallbackMsgCTag::Deny => unsafe { + ConnectionCallbackMessage::Deny(value.data.conn_err.into()) + } + ConnCallbackMsgCTag::Fail => unsafe { + ConnectionCallbackMessage::Fail(value.data.conn_err.into()) + } + ConnCallbackMsgCTag::Ok => { + ConnectionCallbackMessage::Ok + + } + ConnCallbackMsgCTag::Welcome => { + ConnectionCallbackMessage::Welcome + } + ConnCallbackMsgCTag::Err => { + ConnectionCallbackMessage::Err + } + } + } +} + +impl From<ConnectionCallbackMessage> for ConnCallbackMsgC { + fn from(value: ConnectionCallbackMessage) -> Self { + match value { + ConnectionCallbackMessage::Profile(profile) => { + ConnCallbackMsgC { + tag: ConnCallbackMsgCTag::Profile, + data: ConnCallbackMsgCUnion { + profile: ManuallyDrop::new(profile) + } + } + } + ConnectionCallbackMessage::Deny(conn_err) => { + ConnCallbackMsgC { + tag: ConnCallbackMsgCTag::Deny, + data: ConnCallbackMsgCUnion { conn_err: conn_err.into() } + } + } + ConnectionCallbackMessage::Fail(conn_err) => { + ConnCallbackMsgC { + tag: ConnCallbackMsgCTag::Fail, + data: ConnCallbackMsgCUnion { conn_err: conn_err.into() } + } + } + ConnectionCallbackMessage::Ok => { + ConnCallbackMsgC { + tag: ConnCallbackMsgCTag::Ok, + data: ConnCallbackMsgCUnion { nul: null_mut() } + } + } + ConnectionCallbackMessage::Welcome => { + ConnCallbackMsgC { + tag: ConnCallbackMsgCTag::Welcome, + data: ConnCallbackMsgCUnion { nul: null_mut() } + } + } + ConnectionCallbackMessage::Err => { + ConnCallbackMsgC { + tag: ConnCallbackMsgCTag::Err, + data: ConnCallbackMsgCUnion { nul: null_mut() } + } + } + } + } +}
\ No newline at end of file diff --git a/core_c/src/data_c/connection_message_c.rs b/core_c/src/data_c/connection_message_c.rs new file mode 100644 index 0000000..14a49ac --- /dev/null +++ b/core_c/src/data_c/connection_message_c.rs @@ -0,0 +1,95 @@ +use crate::data_c::connection_message_c::ConnMsgCTag::{Connection, Ready, RequestLayoutConfigure, RequestProfile, RequestSkinPackage}; +use std::ffi::c_void; +use std::mem::ManuallyDrop; +use std::ptr::null_mut; +use nogamepads_lib_rs::pad_data::pad_messages::nogamepads_messages::ConnectionMessage; +use nogamepads_lib_rs::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; + +#[repr(C)] +#[allow(unused_imports)] +pub struct ConnMsgC { + tag: ConnMsgCTag, + data: ConnMsgCUnion +} + +#[repr(C)] +#[allow(unused_imports)] +pub enum ConnMsgCTag { + Connection, RequestProfile, RequestLayoutConfigure, RequestSkinPackage, Ready, Err +} + +#[repr(C)] +#[allow(unused_imports)] +pub union ConnMsgCUnion { + nul: *mut c_void, + info: ManuallyDrop<PlayerInfo> +} + +impl From<ConnMsgC> for ConnectionMessage { + fn from(mut value: ConnMsgC) -> Self { + match value.tag { + Connection => unsafe { + let info = ManuallyDrop::take(&mut value.data.info); + ConnectionMessage::Connection(info) + } + RequestProfile => { + ConnectionMessage::RequestProfile + } + RequestLayoutConfigure => { + ConnectionMessage::RequestLayoutConfigure + } + RequestSkinPackage => { + ConnectionMessage::RequestSkinPackage + } + Ready => { + ConnectionMessage::Ready + } + ConnMsgCTag::Err => { + ConnectionMessage::Err + } + } + } +} + +impl From<ConnectionMessage> for ConnMsgC { + fn from(value: ConnectionMessage) -> Self { + match value { + ConnectionMessage::Connection(info) => { + ConnMsgC { + tag: Connection, + data: ConnMsgCUnion { info: ManuallyDrop::new(info) } + } + } + ConnectionMessage::RequestProfile => { + ConnMsgC { + tag: RequestProfile, + data: ConnMsgCUnion { nul: null_mut() } + } + } + ConnectionMessage::RequestLayoutConfigure => { + ConnMsgC { + tag: RequestLayoutConfigure, + data: ConnMsgCUnion { nul: null_mut() } + } + } + ConnectionMessage::RequestSkinPackage => { + ConnMsgC { + tag: RequestSkinPackage, + data: ConnMsgCUnion { nul: null_mut() } + } + } + ConnectionMessage::Ready => { + ConnMsgC { + tag: Ready, + data: ConnMsgCUnion { nul: null_mut() } + } + } + ConnectionMessage::Err => { + ConnMsgC { + tag: ConnMsgCTag::Err, + data: ConnMsgCUnion { nul: null_mut() } + } + } + } + } +}
\ No newline at end of file diff --git a/core_c/src/data_c/control_message_c.rs b/core_c/src/data_c/control_message_c.rs new file mode 100644 index 0000000..41a3e09 --- /dev/null +++ b/core_c/src/data_c/control_message_c.rs @@ -0,0 +1,150 @@ +use crate::data_c::common::KeyData; +use crate::{c_char_to_string_safe, string_to_c_char_safe}; +use nogamepads_lib_rs::pad_data::pad_messages::nogamepads_messages::ControlMessage; +use std::ffi::{c_char, c_void}; +use std::ptr::null_mut; + +#[repr(C)] +#[allow(unused_imports)] +pub struct CtrlMsgC { + tag: CtrlMsgCTag, + data: CtrlMsgCUnion +} + +#[repr(C)] +#[allow(unused_imports)] +pub enum CtrlMsgCTag { + Msg, Pressed, Released, Axis, Dir, Exit, Err +} + +#[repr(C)] +#[allow(unused_imports)] +pub union CtrlMsgCUnion { + nul: *mut c_void, + key: KeyData, + axis: AxisData, + dir: DirData, + str: StrData +} + +#[repr(C)] +#[allow(unused_imports)] +#[derive(Copy, Clone)] +pub struct AxisData { + key: u8, + ax: f64 +} + +#[repr(C)] +#[allow(unused_imports)] +#[derive(Copy, Clone)] +pub struct DirData { + key: u8, + x: f64, + y: f64 +} + +#[repr(C)] +#[allow(unused_imports)] +#[derive(Copy, Clone)] +pub struct StrData { + str: *const c_char +} + +impl From<CtrlMsgC> for ControlMessage { + fn from(msg_c: CtrlMsgC) -> Self { + match msg_c.tag { + CtrlMsgCTag::Msg => unsafe { + let str = c_char_to_string_safe(msg_c.data.str.str); + if str.is_some() { + ControlMessage::Msg(str.unwrap()) + } else { + ControlMessage::Err + } + } + CtrlMsgCTag::Pressed => unsafe { + ControlMessage::Pressed(msg_c.data.key.key) + } + CtrlMsgCTag::Released => unsafe { + ControlMessage::Released(msg_c.data.key.key) + } + CtrlMsgCTag::Axis => unsafe { + let data = msg_c.data.axis; + ControlMessage::Axis(data.key, data.ax) + } + CtrlMsgCTag::Dir => unsafe { + let data = msg_c.data.dir; + ControlMessage::Dir(data.key, (data.x, data.y)) + } + CtrlMsgCTag::Exit => { + ControlMessage::Exit + } + CtrlMsgCTag::Err => { + ControlMessage::Err + } + } + } +} + +impl From<ControlMessage> for CtrlMsgC { + fn from(msg_rs: ControlMessage) -> Self { + match msg_rs { + ControlMessage::Msg(str_msg) => { + CtrlMsgC { + tag: CtrlMsgCTag::Msg, + data: CtrlMsgCUnion { + str: StrData { str: string_to_c_char_safe(str_msg).1 }, + } + } + } + ControlMessage::Pressed(key) => { + CtrlMsgC { + tag: CtrlMsgCTag::Pressed, + data: CtrlMsgCUnion { + key: KeyData { key }, + } + } + } + ControlMessage::Released(key) => { + CtrlMsgC { + tag: CtrlMsgCTag::Released, + data: CtrlMsgCUnion { + key: KeyData { key }, + } + } + } + ControlMessage::Axis(key, ax) => { + CtrlMsgC { + tag: CtrlMsgCTag::Axis, + data: CtrlMsgCUnion { + axis: AxisData { key, ax } + } + } + } + ControlMessage::Dir(key, (x, y)) => { + CtrlMsgC { + tag: CtrlMsgCTag::Dir, + data: CtrlMsgCUnion { + dir: DirData { key, x, y } + } + } + } + ControlMessage::Exit => { + CtrlMsgC { + tag: CtrlMsgCTag::Exit, + data: CtrlMsgCUnion { + nul: null_mut(), + } + } + } + ControlMessage::Err => { + CtrlMsgC { + tag: CtrlMsgCTag::Err, + data: CtrlMsgCUnion { + nul: null_mut(), + } + } + } + } + } +}
\ No newline at end of file diff --git a/core_c/src/data_c/game_message_c.rs b/core_c/src/data_c/game_message_c.rs new file mode 100644 index 0000000..8b275ff --- /dev/null +++ b/core_c/src/data_c/game_message_c.rs @@ -0,0 +1,114 @@ +use std::ffi::c_void; +use std::ptr::null_mut; +use nogamepads_lib_rs::pad_data::pad_messages::nogamepads_messages::{GameMessage, LeaveReason}; +use crate::data_c::common::KeyData; + +#[repr(C)] +#[allow(unused_imports)] +pub struct GameMsgC { + tag: GameMsgCTag, + data: GameMsgCUnion +} + + +#[repr(C)] +#[allow(unused_imports)] +pub enum GameMsgCTag { + SkinEventTrigger, DisableKey, EnableKey, Leave, Err +} + +#[repr(C)] +#[allow(unused_imports)] +pub union GameMsgCUnion { + nul: *mut c_void, + key: KeyData, + reason: LeaveReasonData +} + +#[repr(C)] +#[allow(unused_imports)] +#[derive(Copy, Clone)] +pub enum LeaveReasonData { + GameOver, ServerClosed, YouAreKicked, YouAreBanned +} + +impl From<LeaveReasonData> for LeaveReason { + fn from(value: LeaveReasonData) -> Self { + match value { + LeaveReasonData::GameOver => { LeaveReason::GameOver } + LeaveReasonData::ServerClosed => { LeaveReason::ServerClosed } + LeaveReasonData::YouAreKicked => { LeaveReason::YouAreKicked } + LeaveReasonData::YouAreBanned => { LeaveReason::YouAreBanned } + } + } +} + +impl From<LeaveReason> for LeaveReasonData { + fn from(value: LeaveReason) -> Self { + match value { + LeaveReason::GameOver => { LeaveReasonData::GameOver } + LeaveReason::ServerClosed => { LeaveReasonData::ServerClosed } + LeaveReason::YouAreKicked => { LeaveReasonData::YouAreKicked } + LeaveReason::YouAreBanned => { LeaveReasonData::YouAreBanned } + } + } +} + +impl From<GameMsgC> for GameMessage { + fn from(msg: GameMsgC) -> Self { + match msg.tag { + GameMsgCTag::SkinEventTrigger => unsafe { + GameMessage::SkinEventTrigger(msg.data.key.key) + } + GameMsgCTag::DisableKey => unsafe { + GameMessage::DisableKey(msg.data.key.key) + } + GameMsgCTag::EnableKey => unsafe { + GameMessage::EnableKey(msg.data.key.key) + } + GameMsgCTag::Leave => unsafe { + GameMessage::Leave(msg.data.reason.into()) + } + GameMsgCTag::Err => { + GameMessage::Err + } + } + } +} + +impl From<GameMessage> for GameMsgC { + fn from(msg: GameMessage) -> Self { + match msg { + GameMessage::SkinEventTrigger(key) => { + GameMsgC { + tag: GameMsgCTag::SkinEventTrigger, + data: GameMsgCUnion { key: KeyData { key } } + } + } + GameMessage::DisableKey(key) => { + GameMsgC { + tag: GameMsgCTag::DisableKey, + data: GameMsgCUnion { key: KeyData { key } } + } + } + GameMessage::EnableKey(key) => { + GameMsgC { + tag: GameMsgCTag::EnableKey, + data: GameMsgCUnion { key: KeyData { key } } + } + } + GameMessage::Leave(reason) => { + GameMsgC { + tag: GameMsgCTag::Leave, + data: GameMsgCUnion { reason: reason.into() } + } + } + GameMessage::Err => { + GameMsgC { + tag: GameMsgCTag::Err, + data: GameMsgCUnion { nul: null_mut() } + } + } + } + } +}
\ No newline at end of file diff --git a/core_c/src/data_c/game_profile_c.rs b/core_c/src/data_c/game_profile_c.rs new file mode 100644 index 0000000..199329a --- /dev/null +++ b/core_c/src/data_c/game_profile_c.rs @@ -0,0 +1,44 @@ +use std::ffi::c_char; +use crate::{box_into_raw, c_char_to_string_safe}; +use nogamepads_lib_rs::pad_data::game_profile::game_profile::GameProfile; + +#[unsafe(no_mangle)] +pub extern "C" fn init_game_profile() -> *mut GameProfile { + box_into_raw!(GameProfile::default()) +} + +#[unsafe(no_mangle)] +pub extern "C" fn set_game_profile_name(game_profile: &mut GameProfile, value: *const c_char) { + let value = c_char_to_string_safe(value).unwrap_or_default(); + game_profile.game_name(value.as_str()); +} + +#[unsafe(no_mangle)] +pub extern "C" fn set_game_profile_description(game_profile: &mut GameProfile, value: *const c_char) { + let value = c_char_to_string_safe(value).unwrap_or_default(); + game_profile.game_description(value.as_str()); +} + +#[unsafe(no_mangle)] +pub extern "C" fn set_game_profile_organization(game_profile: &mut GameProfile, value: *const c_char) { + let value = c_char_to_string_safe(value).unwrap_or_default(); + game_profile.organization(value.as_str()); +} + +#[unsafe(no_mangle)] +pub extern "C" fn set_game_profile_version(game_profile: &mut GameProfile, value: *const c_char) { + let value = c_char_to_string_safe(value).unwrap_or_default(); + game_profile.version(value.as_str()); +} + +#[unsafe(no_mangle)] +pub extern "C" fn set_game_profile_website(game_profile: &mut GameProfile, value: *const c_char) { + let value = c_char_to_string_safe(value).unwrap_or_default(); + game_profile.website(value.as_str()); +} + +#[unsafe(no_mangle)] +pub extern "C" fn set_game_profile_email(game_profile: &mut GameProfile, value: *const c_char) { + let value = c_char_to_string_safe(value).unwrap_or_default(); + game_profile.email(value.as_str()); +}
\ No newline at end of file diff --git a/core_c/src/data_c/mod.rs b/core_c/src/data_c/mod.rs new file mode 100644 index 0000000..afe8728 --- /dev/null +++ b/core_c/src/data_c/mod.rs @@ -0,0 +1,11 @@ +pub mod common; + +pub mod control_message_c; +pub mod game_message_c; +pub mod connection_message_c; +pub mod connection_callback_message_c; + + +pub mod game_profile_c; +pub mod player_info_c; +pub mod player_info_list_c;
\ No newline at end of file diff --git a/core_c/src/data_c/player_info_c.rs b/core_c/src/data_c/player_info_c.rs new file mode 100644 index 0000000..4252b49 --- /dev/null +++ b/core_c/src/data_c/player_info_c.rs @@ -0,0 +1,33 @@ +use std::ffi::c_char; +use nogamepads_lib_rs::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; +use crate::{box_into_raw, c_char_to_string_safe}; + +#[unsafe(no_mangle)] +pub extern "C" fn init_player_info() -> *mut PlayerInfo { + box_into_raw!(PlayerInfo::new()) +} + +#[unsafe(no_mangle)] +pub extern "C" fn set_player_info_account( + info: &mut PlayerInfo, + id: *const c_char, + password: *const c_char) { + let id = c_char_to_string_safe(id).unwrap_or("".to_string()); + let password = c_char_to_string_safe(password).unwrap_or("".to_string()); + info.setup_account_info(id.as_str(), password.as_str()); +} + +#[unsafe(no_mangle)] +pub extern "C" fn set_player_info_color( + info: &mut PlayerInfo, + h: i32, s: f64, v: f64) { + info.set_customize_color_hsv(h, s, v); +} + +#[unsafe(no_mangle)] +pub extern "C" fn set_player_info_nickname( + info: &mut PlayerInfo, + nickname: *const c_char) { + let nickname = c_char_to_string_safe(nickname).unwrap_or("".to_string()); + info.set_nickname(nickname.as_str()); +}
\ No newline at end of file diff --git a/core_c/src/data_c/player_info_list_c.rs b/core_c/src/data_c/player_info_list_c.rs new file mode 100644 index 0000000..9ad8918 --- /dev/null +++ b/core_c/src/data_c/player_info_list_c.rs @@ -0,0 +1,8 @@ +use nogamepads_lib_rs::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; + +#[repr(C)] +pub struct PlayerList { + pub(crate) players: *mut PlayerInfo, + pub(crate) len: usize, + pub(crate) capacity: usize, +}
\ No newline at end of file diff --git a/core_c/src/service_c/common.rs b/core_c/src/service_c/common.rs new file mode 100644 index 0000000..8b13da0 --- /dev/null +++ b/core_c/src/service_c/common.rs @@ -0,0 +1,4 @@ +use nogamepads_lib_rs::DEFAULT_PORT; + +#[unsafe(no_mangle)] +pub extern "C" fn get_default_port() -> u16 { DEFAULT_PORT }
\ No newline at end of file diff --git a/core_c/src/service_c/mod.rs b/core_c/src/service_c/mod.rs new file mode 100644 index 0000000..c3d23af --- /dev/null +++ b/core_c/src/service_c/mod.rs @@ -0,0 +1,4 @@ +pub mod common; + +pub mod padclient; +mod padserver;
\ No newline at end of file diff --git a/core_c/src/service_c/padclient.rs b/core_c/src/service_c/padclient.rs new file mode 100644 index 0000000..77e7d87 --- /dev/null +++ b/core_c/src/service_c/padclient.rs @@ -0,0 +1,73 @@ +use std::ffi::c_char; +use std::net::{IpAddr, Ipv4Addr}; +use std::str::FromStr; +use nogamepads_lib_rs::DEFAULT_PORT; +use nogamepads_lib_rs::pad_data::pad_messages::nogamepads_messages::GameMessage; +use nogamepads_lib_rs::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; +use nogamepads_lib_rs::pad_service::client::nogamepads_client::PadClient; +use crate::{box_into_raw, c_char_to_string_safe}; +use crate::data_c::control_message_c::CtrlMsgC; +use crate::data_c::game_message_c::GameMsgC; + +// 构建 + +#[unsafe(no_mangle)] +pub extern "C" fn init_client(address: *const c_char) -> *mut PadClient { + let addr_str = c_char_to_string_safe(address).unwrap_or("127.0.0.1".to_string()); + let addr_v4 = Ipv4Addr::from_str(addr_str.as_str()).unwrap_or( + Ipv4Addr::new(127, 0, 0, 1)); + box_into_raw!(PadClient::bind_addr_with_port(IpAddr::from(addr_v4), DEFAULT_PORT)) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn init_client_with_port(address: *const c_char, port: u16) -> *mut PadClient { + let addr_str = c_char_to_string_safe(address).unwrap_or("127.0.0.1".to_string()); + let addr_v4 = Ipv4Addr::from_str(addr_str.as_str()).unwrap_or( + Ipv4Addr::new(127, 0, 0, 1)); + box_into_raw!(PadClient::bind_addr_with_port(IpAddr::from(addr_v4), port)) +} + +#[unsafe(no_mangle)] +pub extern "C" fn set_client_quiet(client: &mut PadClient) { + client.quiet(); +} + +#[unsafe(no_mangle)] +pub extern "C" fn enable_client_console(client: &mut PadClient) { + client.enable_console(); +} + +#[unsafe(no_mangle)] +pub extern "C" fn bind_player_to_client(client: &mut PadClient, info: &mut PlayerInfo) { + client.bind_player(info.clone()); +} + +// 状态控制 + +#[unsafe(no_mangle)] +pub extern "C" fn connect_client_to_server(client: *mut PadClient) { + let client = unsafe { Box::from_raw(client) }; + client.connect(); +} + +#[unsafe(no_mangle)] +pub extern "C" fn exit_client_from_server(client: &PadClient) { + client.exit_server(); +} + +// 消息管理 + +#[unsafe(no_mangle)] +pub extern "C" fn put_a_msg_to_server(client: &PadClient, msg: CtrlMsgC) { + client.put_msg(msg.into()) +} + +#[unsafe(no_mangle)] +pub extern "C" fn pop_a_msg_from_server(client: &PadClient) -> GameMsgC { + client.pop_a_msg().unwrap_or(GameMessage::Err).into() +} + +#[unsafe(no_mangle)] +pub extern "C" fn pop_msg_from_server_or(client: &PadClient, or: GameMsgC) -> GameMsgC { + client.pop_msg_or(or.into()).into() +}
\ No newline at end of file diff --git a/core_c/src/service_c/padserver.rs b/core_c/src/service_c/padserver.rs new file mode 100644 index 0000000..d0e3267 --- /dev/null +++ b/core_c/src/service_c/padserver.rs @@ -0,0 +1,175 @@ +use std::collections::HashMap; +use crate::{box_into_raw, c_char_to_string_safe}; +use nogamepads_lib_rs::pad_data::game_profile::game_profile::GameProfile; +use nogamepads_lib_rs::pad_service::server::nogamepads_server::PadServer; +use nogamepads_lib_rs::DEFAULT_PORT; +use std::ffi::c_char; +use std::net::{IpAddr, Ipv4Addr}; +use std::str::FromStr; +use std::sync::{Arc, MutexGuard, PoisonError}; +use nogamepads_lib_rs::pad_data::pad_messages::nogamepads_messages::ControlMessage; +use nogamepads_lib_rs::pad_data::pad_player_info::nogamepads_player_info::PlayerInfo; +use crate::data_c::control_message_c::CtrlMsgC; +use crate::data_c::game_message_c::GameMsgC; +use crate::data_c::player_info_list_c::PlayerList; + +// 构建 + +#[unsafe(no_mangle)] +pub extern "C" fn init_server(address: *const c_char) -> *mut PadServer { + let addr_str = c_char_to_string_safe(address).unwrap_or("127.0.0.1".to_string()); + let addr_v4 = Ipv4Addr::from_str(addr_str.as_str()).unwrap_or( + Ipv4Addr::new(127, 0, 0, 1)); + let mut server = PadServer::default(); + server.addr(IpAddr::from(addr_v4), DEFAULT_PORT); + box_into_raw!(server) +} + +#[unsafe(no_mangle)] +pub extern "C" fn init_server_with_port(address: *const c_char, port: u16) -> *mut PadServer { + let addr_str = c_char_to_string_safe(address).unwrap_or("127.0.0.1".to_string()); + let addr_v4 = Ipv4Addr::from_str(addr_str.as_str()).unwrap_or( + Ipv4Addr::new(127, 0, 0, 1)); + let mut server = PadServer::default(); + server.addr(IpAddr::from(addr_v4), port); + box_into_raw!(server) +} + +#[unsafe(no_mangle)] +pub extern "C" fn set_server_quiet(server: &mut PadServer) { + server.quiet(); +} + +#[unsafe(no_mangle)] +pub extern "C" fn enable_server_console(server: &mut PadServer) { + server.enable_console(); +} + +#[unsafe(no_mangle)] +pub extern "C" fn bind_profile_to_server(server: &mut PadServer, profile: &mut GameProfile) { + server.put_profile(profile.clone()); +} + +// 状态控制 + +#[unsafe(no_mangle)] +pub extern "C" fn start_server(server: *mut PadServer) { + let server = unsafe { Box::from_raw(server) }; + let arc = Arc::new(server.as_ref().clone()); + PadServer::start_server(arc); +} + +#[unsafe(no_mangle)] +pub extern "C" fn stop_server(server: *mut PadServer) { + let server = unsafe { Box::from_raw(server) }; + server.stop_server(); +} + +#[unsafe(no_mangle)] +pub extern "C" fn lock_game_on_server(server: *mut PadServer) { + let server = unsafe { Box::from_raw(server) }; + server.lock_game(); +} + +#[unsafe(no_mangle)] +pub extern "C" fn unlock_game_on_server(server: *mut PadServer) { + let server = unsafe { Box::from_raw(server) }; + server.unlock_game(); +} + +#[unsafe(no_mangle)] +pub extern "C" fn is_server_game_locked(server: *mut PadServer) -> bool { + let server = unsafe { Box::from_raw(server) }; + server.is_game_locked() +} + +// 消息管理 +#[unsafe(no_mangle)] +pub extern "C" fn put_a_msg_to_player(server: *mut PadServer, msg: GameMsgC, player: &PlayerInfo) { + let server = unsafe { Box::from_raw(server) }; + server.put_msg_to(msg.into(), player); +} + +#[unsafe(no_mangle)] +pub extern "C" fn put_msg_to_all_players(server: *mut PadServer, msg: GameMsgC) { + let server = unsafe { Box::from_raw(server) }; + server.put_msg_to_all(&msg.into()); +} + +#[unsafe(no_mangle)] +pub extern "C" fn pop_a_msg_from_player(server: *mut PadServer, player: &PlayerInfo) -> CtrlMsgC { + let server = unsafe { Box::from_raw(server) }; + server.pop_a_msg(player).unwrap_or(ControlMessage::Err).into() +} + +#[unsafe(no_mangle)] +pub extern "C" fn pop_msg_from_player_or(server: *mut PadServer, player: &PlayerInfo, or: CtrlMsgC) -> CtrlMsgC { + let server = unsafe { Box::from_raw(server) }; + let msg = server.pop_msg_or(player, or.into()); + msg.into() +} + +// 玩家管理 +#[unsafe(no_mangle)] +pub extern "C" fn is_player_online(server: *mut PadServer, player: &PlayerInfo) -> bool { + let server = unsafe { Box::from_raw(server) }; + server.is_player_online(player) +} + +#[unsafe(no_mangle)] +pub extern "C" fn is_player_banned(server: *mut PadServer, player: &PlayerInfo) -> bool { + let server = unsafe { Box::from_raw(server) }; + server.is_player_banned(player) +} + +#[unsafe(no_mangle)] +pub extern "C" fn kick_player(server: *mut PadServer, player: &PlayerInfo) { + let server = unsafe { Box::from_raw(server) }; + server.kick_player(player); +} + +#[unsafe(no_mangle)] +pub extern "C" fn ban_player(server: *mut PadServer, player: &PlayerInfo) { + let server = unsafe { Box::from_raw(server) }; + server.ban_player(player); +} + +#[unsafe(no_mangle)] +pub extern "C" fn pardon_player(server: *mut PadServer, player: &PlayerInfo) { + let server = unsafe { Box::from_raw(server) }; + server.pardon_player(player); +} + +#[unsafe(no_mangle)] +pub extern "C" fn list_online_players(server: *mut PadServer) -> PlayerList { + let server = unsafe { Box::from_raw(server) }; + let list = server.list_players(); + process_list_result(list) +} + +#[unsafe(no_mangle)] +pub extern "C" fn list_banned_players(server: *mut PadServer) -> PlayerList { + let server = unsafe { Box::from_raw(server) }; + let list = server.list_players_banned(); + process_list_result(list) +} + +fn process_list_result(list: Result<Vec<PlayerInfo>, PoisonError<MutexGuard<HashMap<String, PlayerInfo>>>>) -> PlayerList { + let result : Vec<PlayerInfo>; + if list.is_ok() { + result = list.unwrap(); + } else { + result = vec![]; + } + + let mut vec = result.into_boxed_slice(); + let ptr = vec.as_mut_ptr(); + let len = vec.len(); + let capacity = vec.len(); + + PlayerList { + players: ptr, + len, + capacity + } +}
\ No newline at end of file |
