Skip to content

Commit

Permalink
Avoid freeing CString by the C free() function
Browse files Browse the repository at this point in the history
  • Loading branch information
ken-matsui committed May 9, 2022
1 parent 46648aa commit c461db0
Showing 1 changed file with 46 additions and 37 deletions.
83 changes: 46 additions & 37 deletions src/c_api.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,55 @@
use crate::ext;

use std::ffi::{CStr, CString};
use std::mem;
use std::os::raw::c_char;

/// # Safety
///
/// This public function might dereference a raw pointer.
/// The returned char pointer should be freed by the `cstring_free` function.
/// For detailed usage in any language, please see:
/// https://jakegoulding.com/rust-ffi-omnibus/string_return/
#[no_mangle]
pub unsafe extern "C" fn to_json(from: ext::Ext, text: *const c_char) -> *const c_char {
let text_c_str = CStr::from_ptr(text);
let value = ext::deserialize::<ext::json::Value>(from, text_c_str.to_str().unwrap());
let output = CString::new(ext::json::serialize(&value.unwrap()).unwrap()).unwrap();
let ptr = output.as_ptr();
mem::forget(output);
ptr
pub unsafe extern "C" fn to_json(from: ext::Ext, input: *const c_char) -> *mut c_char {
let input = CStr::from_ptr(input);
let deserialized = ext::deserialize::<ext::json::Value>(from, input.to_str().unwrap());
let serialized = CString::new(ext::json::serialize(&deserialized.unwrap()).unwrap()).unwrap();
serialized.into_raw()
}

/// # Safety
///
/// This public function might dereference a raw pointer.
/// The returned char pointer should be freed by the `cstring_free` function.
/// For detailed usage in any language, please see:
/// https://jakegoulding.com/rust-ffi-omnibus/string_return/
#[no_mangle]
pub unsafe extern "C" fn to_yaml(from: ext::Ext, text: *const c_char) -> *const c_char {
let text_c_str = CStr::from_ptr(text);
let value = ext::deserialize::<ext::yaml::Value>(from, text_c_str.to_str().unwrap());
let output = CString::new(ext::yaml::serialize(&value.unwrap()).unwrap()).unwrap();
let ptr = output.as_ptr();
mem::forget(output);
ptr
pub unsafe extern "C" fn to_yaml(from: ext::Ext, input: *const c_char) -> *mut c_char {
let input = CStr::from_ptr(input);
let deserialized = ext::deserialize::<ext::yaml::Value>(from, input.to_str().unwrap());
let serialized = CString::new(ext::yaml::serialize(&deserialized.unwrap()).unwrap()).unwrap();
serialized.into_raw()
}

/// # Safety
///
/// This public function might dereference a raw pointer.
/// The returned char pointer should be freed by the `cstring_free` function.
/// For detailed usage in any language, please see:
/// https://jakegoulding.com/rust-ffi-omnibus/string_return/
#[no_mangle]
pub unsafe extern "C" fn to_toml(from: ext::Ext, text: *const c_char) -> *const c_char {
let text_c_str = CStr::from_ptr(text);
let value = ext::deserialize::<ext::toml::Value>(from, text_c_str.to_str().unwrap());
let output = CString::new(ext::toml::serialize(&value.unwrap()).unwrap()).unwrap();
let ptr = output.as_ptr();
mem::forget(output);
ptr
pub unsafe extern "C" fn to_toml(from: ext::Ext, input: *const c_char) -> *mut c_char {
let input = CStr::from_ptr(input);
let deserialized = ext::deserialize::<ext::toml::Value>(from, input.to_str().unwrap());
let serialized = CString::new(ext::toml::serialize(&deserialized.unwrap()).unwrap()).unwrap();
serialized.into_raw()
}

#[no_mangle]
pub extern "C" fn cstring_free(s: *mut c_char) {
unsafe {
if s.is_null() {
return;
}
CString::from_raw(s)
};
}

#[cfg(test)]
Expand Down Expand Up @@ -115,9 +124,9 @@ enabled = true
" \"enabled\": true\n"
" }\n"
"}";
const char* output = to_yaml(Json, input);
char* output = to_yaml(Json, input);
printf("%s", output);
free((char*)output);
cstring_free(output);
return 0;
}
})
Expand Down Expand Up @@ -149,9 +158,9 @@ enabled = true
" \"enabled\": true\n"
" }\n"
"}";
const char* output = to_toml(Json, input);
char* output = to_toml(Json, input);
printf("%s", output);
free((char*)output);
cstring_free(output);
return 0;
}
})
Expand Down Expand Up @@ -180,9 +189,9 @@ enabled = true
" - 8002\n"
" connection_max: 5000\n"
" enabled: true\n";
const char* output = to_json(Yaml, input);
char* output = to_json(Yaml, input);
printf("%s", output);
free((char*)output);
cstring_free(output);
return 0;
}
})
Expand Down Expand Up @@ -210,9 +219,9 @@ enabled = true
" - 8002\n"
" connection_max: 5000\n"
" enabled: true\n";
const char* output = to_toml(Yaml, input);
char* output = to_toml(Yaml, input);
printf("%s", output);
free((char*)output);
cstring_free(output);
return 0;
}
})
Expand All @@ -239,9 +248,9 @@ enabled = true
"ports = [8000, 8001, 8002]\n"
"connection_max = 5000\n"
"enabled = true\n";
const char* output = to_json(Toml, input);
char* output = to_json(Toml, input);
printf("%s", output);
free((char*)output);
cstring_free(output);
return 0;
}
})
Expand All @@ -267,9 +276,9 @@ enabled = true
"ports = [8000, 8001, 8002]\n"
"connection_max = 5000\n"
"enabled = true\n";
const char* output = to_yaml(Toml, input);
char* output = to_yaml(Toml, input);
printf("%s", output);
free((char*)output);
cstring_free(output);
return 0;
}
})
Expand Down

0 comments on commit c461db0

Please sign in to comment.