Skip to content

Commit 1c24552

Browse files
authored
CON-382: Feedback on FFI conventions (#10)
There are some idioms in Rust more suitable for our code, such as using `std::ptr::NonNull`. We should prefer these to enforce a safer and cleaner code. * `Native{}` now holds a `NonNull<T>` instead of a `*const T`. * FFI calls that take a pointer "self" argument prefer `NonNull<T>`, because the C API expects non-null and `NonNull<T>` is transparent over `*const T`. Additionally, we could use the chance to revisit the naming conventions on FFI-related types to better reflect their nature. * `Native{}` --> `Ffi{}`: "Native" could refer to anything, but FFI implies "glue". * `{}Ptr` --> `Opaque{}`: The types were never pointers to begin with.
1 parent a126f58 commit 1c24552

File tree

3 files changed

+80
-84
lines changed

3 files changed

+80
-84
lines changed

src/connector.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/docs/connector.md"))]
1010

1111
use crate::{
12-
ConnectorFallible, ConnectorResult, Input, Output, ffi::NativeConnector,
12+
ConnectorFallible, ConnectorResult, Input, Output, ffi::FfiConnector,
1313
result::ErrorKind,
1414
};
1515
use std::{
@@ -99,7 +99,7 @@ pub struct Connector {
9999
name: String,
100100

101101
/// The native connector instance, protected by a RwLock for thread-safe access.
102-
native: RwLock<NativeConnector>,
102+
native: RwLock<FfiConnector>,
103103

104104
/// Thread-safe holders for Input entities.
105105
inputs: ThreadSafeEntityHolder<InputRecord>,
@@ -136,7 +136,7 @@ impl Connector {
136136
static VERSION_STRING: &str = env!("CARGO_PKG_VERSION");
137137

138138
let (ndds_build_id_string, rtiddsconnector_build_id_string) =
139-
NativeConnector::get_build_versions().unwrap_or((
139+
FfiConnector::get_build_versions().unwrap_or((
140140
"<Unknown RTI Connext version>".to_string(),
141141
"<Unknown RTI Connector for Rust version>".to_string(),
142142
));
@@ -149,22 +149,22 @@ impl Connector {
149149

150150
/// Get the last error message from the underlying RTI Connector C API.
151151
pub(crate) fn get_last_error_message() -> Option<String> {
152-
NativeConnector::get_last_error_message()
152+
FfiConnector::get_last_error_message()
153153
}
154154

155155
/// Create a new [`Connector`] from a named configuration contained
156156
/// in an external XML file.
157157
pub fn new(config_name: &str, config_file: &str) -> ConnectorResult<Connector> {
158158
static NATIVE_CONNECTOR_CREATION_LOCK: Mutex<()> = Mutex::new(());
159159

160-
let native: NativeConnector = {
160+
let native: FfiConnector = {
161161
let _guard = NATIVE_CONNECTOR_CREATION_LOCK
162162
.lock()
163163
.inspect_err(|_| {
164164
eprintln!("An error occurred while trying to lock the global native connector creation lock, continuing anyway...");
165165
})
166166
.unwrap_or_else(|poisoned| poisoned.into_inner());
167-
NativeConnector::new(config_name, config_file)?
167+
FfiConnector::new(config_name, config_file)?
168168
};
169169

170170
Ok(Connector {
@@ -254,10 +254,10 @@ impl Connector {
254254
self.outputs.release_entity(name)
255255
}
256256

257-
/// Get immutable access to the [`NativeConnector`] (for read operations)
257+
/// Get immutable access to the [`FfiConnector`] (for read operations)
258258
pub(crate) fn native_ref(
259259
&self,
260-
) -> ConnectorResult<std::sync::RwLockReadGuard<'_, NativeConnector>> {
260+
) -> ConnectorResult<std::sync::RwLockReadGuard<'_, FfiConnector>> {
261261
self.native.read().map_err(|_| {
262262
ErrorKind::lock_poisoned_error(
263263
"Another thread panicked while holding the native connector lock",
@@ -266,10 +266,10 @@ impl Connector {
266266
})
267267
}
268268

269-
/// Get mutable access to the [`NativeConnector`] (for write operations)
269+
/// Get mutable access to the [`FfiConnector`] (for write operations)
270270
pub(crate) fn native_mut(
271271
&self,
272-
) -> ConnectorResult<std::sync::RwLockWriteGuard<'_, NativeConnector>> {
272+
) -> ConnectorResult<std::sync::RwLockWriteGuard<'_, FfiConnector>> {
273273
self.native.write().map_err(|_| {
274274
ErrorKind::lock_poisoned_error(
275275
"Another thread panicked while holding the native connector lock",

src/ffi/mod.rs

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub use rtiddsconnector::ReturnCode;
2020

2121
use crate::result::ErrorKind;
2222
use rtiddsconnector::{ConnectorIndex, NativeAllocatedString, NativeStringTrait};
23-
use std::ffi::CString;
23+
use std::{ffi::CString, ptr::NonNull};
2424

2525
/// Helper for converting a [`std::ffi::NulError`] into a [`ConnectorError`][crate::ConnectorError]
2626
impl From<std::ffi::NulError> for crate::ConnectorError {
@@ -67,12 +67,12 @@ impl GlobalsDropGuard {
6767

6868
/// Newtype wrappers for native Sample pointers
6969
#[allow(unused)]
70-
pub struct NativeSample(*const rtiddsconnector::SamplePtr);
70+
pub struct FfiSample(NonNull<rtiddsconnector::OpaqueSample>);
7171

7272
/// Newtype wrappers for native DataReader pointers
73-
pub struct NativeInput(*const rtiddsconnector::DataReaderPtr);
73+
pub struct FfiInput(NonNull<rtiddsconnector::OpaqueDataReader>);
7474

75-
impl NativeInput {
75+
impl FfiInput {
7676
pub fn wait_for_matched_publication(
7777
&self,
7878
timeout: Option<i32>,
@@ -106,9 +106,9 @@ impl NativeInput {
106106
}
107107

108108
/// Newtype wrappers for native DataWriter pointers
109-
pub struct NativeOutput(*const rtiddsconnector::DataWriterPtr);
109+
pub struct FfiOutput(NonNull<rtiddsconnector::OpaqueDataWriter>);
110110

111-
impl NativeOutput {
111+
impl FfiOutput {
112112
pub fn wait_for_matched_subscription(
113113
&self,
114114
timeout: Option<i32>,
@@ -145,55 +145,52 @@ impl NativeOutput {
145145
}
146146

147147
/// Newtype wrappers for native Connector pointers
148-
pub struct NativeConnector(*const rtiddsconnector::ConnectorPtr);
148+
pub struct FfiConnector(NonNull<rtiddsconnector::OpaqueConnector>);
149149

150-
impl Drop for NativeConnector {
150+
impl Drop for FfiConnector {
151151
fn drop(&mut self) {
152152
if let Err(e) = self.delete() {
153153
eprintln!("ERROR: failed to delete native participant: {}", e);
154154
}
155155
}
156156
}
157157

158-
impl NativeConnector {
158+
impl FfiConnector {
159159
pub fn new(
160160
connector_name: &str,
161161
config_file: &str,
162-
) -> crate::ConnectorResult<NativeConnector> {
162+
) -> crate::ConnectorResult<FfiConnector> {
163163
let config_name = CString::new(connector_name)?;
164164
let config_file = CString::new(config_file)?;
165165

166-
unsafe {
166+
NonNull::new(unsafe {
167167
rtiddsconnector::RTI_Connector_new(
168168
config_name.as_ptr(),
169169
config_file.as_ptr(),
170170
&rtiddsconnector::ConnectorOptions::default(),
171171
)
172-
.as_ref()
173-
}
174-
.map(|ptr| NativeConnector(ptr))
172+
})
173+
.map(FfiConnector)
175174
.ok_or_else(|| ErrorKind::entity_not_found_error(connector_name).into())
176175
}
177176

178-
pub fn get_output(&self, output_name: &str) -> crate::ConnectorResult<NativeOutput> {
177+
pub fn get_output(&self, output_name: &str) -> crate::ConnectorResult<FfiOutput> {
179178
let entity_name = CString::new(output_name)?;
180179

181-
unsafe {
180+
NonNull::new(unsafe {
182181
rtiddsconnector::RTI_Connector_get_datawriter(self.0, entity_name.as_ptr())
183-
.as_ref()
184-
}
185-
.map(|ptr| NativeOutput(ptr))
182+
})
183+
.map(FfiOutput)
186184
.ok_or_else(|| ErrorKind::entity_not_found_error(output_name).into())
187185
}
188186

189-
pub fn get_input(&self, input_name: &str) -> crate::ConnectorResult<NativeInput> {
187+
pub fn get_input(&self, input_name: &str) -> crate::ConnectorResult<FfiInput> {
190188
let entity_name = CString::new(input_name)?;
191189

192-
unsafe {
190+
NonNull::new(unsafe {
193191
rtiddsconnector::RTI_Connector_get_datareader(self.0, entity_name.as_ptr())
194-
.as_ref()
195-
}
196-
.map(|ptr| NativeInput(ptr))
192+
})
193+
.map(FfiInput)
197194
.ok_or_else(|| ErrorKind::entity_not_found_error(input_name).into())
198195
}
199196

@@ -202,25 +199,24 @@ impl NativeConnector {
202199
&self,
203200
output_name: &str,
204201
index: usize,
205-
) -> crate::ConnectorResult<NativeSample> {
202+
) -> crate::ConnectorResult<FfiSample> {
206203
let entity_name: CString = CString::new(output_name)?;
207204
let index: ConnectorIndex = index.try_into()?;
208205

209-
unsafe {
206+
NonNull::new(unsafe {
210207
rtiddsconnector::RTI_Connector_get_native_sample(
211208
self.0,
212209
entity_name.as_ptr(),
213210
index,
214211
)
215-
.as_ref()
216-
}
217-
.map(|ptr| NativeSample(ptr))
212+
})
213+
.map(FfiSample)
218214
.ok_or_else(|| ErrorKind::entity_not_found_error(output_name).into())
219215
}
220216

221217
fn delete(&mut self) -> crate::ConnectorFallible {
222218
InvokeResult::never_fails(|| unsafe {
223-
rtiddsconnector::RTI_Connector_delete(self.0)
219+
rtiddsconnector::RTI_Connector_delete(self.0.as_ptr())
224220
})
225221
.into()
226222
}
@@ -649,7 +645,7 @@ impl NativeConnector {
649645
pub fn get_native_instance(
650646
&self,
651647
entity_name: &str,
652-
) -> crate::ConnectorResult<*const rtiddsconnector::SamplePtr> {
648+
) -> crate::ConnectorResult<*const rtiddsconnector::OpaqueSample> {
653649
unimplemented!();
654650
}
655651

0 commit comments

Comments
 (0)