Skip to content

Commit

Permalink
Merge pull request #89 from kenz-gelsoft/wx_string
Browse files Browse the repository at this point in the history
Fix wxString leaks and lifetime problems
  • Loading branch information
kenz-gelsoft authored Jun 18, 2022
2 parents 32df788 + 9ac8d1d commit 4b9a1fd
Show file tree
Hide file tree
Showing 8 changed files with 524 additions and 271 deletions.
9 changes: 6 additions & 3 deletions doxybindgen/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ def _wrap(self, call=""):
returns = self.__wrapped[2:]
if self.__returns.is_str():
return ['String',
'from_wx_string(%s)' % (call,)]
'WxString::from_ptr(%s).into()' % (call,)]
if self.is_ctor:
return ['%sIsOwned<OWNED>' % (returns,),
'%sIsOwned(%s)' % (returns, call)]
Expand Down Expand Up @@ -461,11 +461,14 @@ def in_cxx(self):
def marshal(self, param):
name = camel_to_snake(param.name)
if self._is_const_ref_to_string():
yield 'let %s = wx_string_from(%s);' % (
# This variable keeps temporary wxString object in this scope.
yield 'let %s = WxString::from(%s);' % (
name,
name,
)
if self.is_const_ref_to_binding():
if (self.is_const_ref_to_binding() or
# So, taking pointer must be another expression for its lifetime.
self._is_const_ref_to_string()):
yield 'let %s = %s;' % (
name,
param.rust_ffi_ref(),
Expand Down
1 change: 1 addition & 0 deletions wx-base/include/manual.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct UTF8Data {
size_t length;
};
wxString *wxString_new(const unsigned char *psz, const size_t nLength);
void wxString_delete(wxString *self);
UTF8Data wxString_UTF8Data(wxString *self);

// (wx)String::const_iterator
Expand Down
34 changes: 21 additions & 13 deletions wx-base/src/generated/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,27 +200,29 @@ pub trait DateTimeMethods: WxRustMethods {
// NOT_SUPPORTED: fn operator-2()
fn format(&self, format: &str, tz: *const c_void) -> String {
unsafe {
let format = wx_string_from(format);
from_wx_string(ffi::wxDateTime_Format(self.as_ptr(), format, tz))
let format = WxString::from(format);
let format = format.as_ptr();
WxString::from_ptr(ffi::wxDateTime_Format(self.as_ptr(), format, tz)).into()
}
}
fn format_date(&self) -> String {
unsafe { from_wx_string(ffi::wxDateTime_FormatDate(self.as_ptr())) }
unsafe { WxString::from_ptr(ffi::wxDateTime_FormatDate(self.as_ptr())).into() }
}
// NOT_SUPPORTED: fn FormatISOCombined()
fn format_iso_date(&self) -> String {
unsafe { from_wx_string(ffi::wxDateTime_FormatISODate(self.as_ptr())) }
unsafe { WxString::from_ptr(ffi::wxDateTime_FormatISODate(self.as_ptr())).into() }
}
fn format_iso_time(&self) -> String {
unsafe { from_wx_string(ffi::wxDateTime_FormatISOTime(self.as_ptr())) }
unsafe { WxString::from_ptr(ffi::wxDateTime_FormatISOTime(self.as_ptr())).into() }
}
fn format_time(&self) -> String {
unsafe { from_wx_string(ffi::wxDateTime_FormatTime(self.as_ptr())) }
unsafe { WxString::from_ptr(ffi::wxDateTime_FormatTime(self.as_ptr())).into() }
}
// BLOCKED: fn ParseDate()
fn parse_date_time(&self, datetime: &str, end: *mut c_void) -> bool {
unsafe {
let datetime = wx_string_from(datetime);
let datetime = WxString::from(datetime);
let datetime = datetime.as_ptr();
ffi::wxDateTime_ParseDateTime(self.as_ptr(), datetime, end)
}
}
Expand All @@ -232,8 +234,10 @@ pub trait DateTimeMethods: WxRustMethods {
end: *mut c_void,
) -> bool {
unsafe {
let date = wx_string_from(date);
let format = wx_string_from(format);
let date = WxString::from(date);
let date = date.as_ptr();
let format = WxString::from(format);
let format = format.as_ptr();
let date_def = date_def.as_ptr();
ffi::wxDateTime_ParseFormat(self.as_ptr(), date, format, date_def, end)
}
Expand All @@ -243,25 +247,29 @@ pub trait DateTimeMethods: WxRustMethods {
// NOT_SUPPORTED: fn ParseISOCombined()
fn parse_iso_date(&self, date: &str) -> bool {
unsafe {
let date = wx_string_from(date);
let date = WxString::from(date);
let date = date.as_ptr();
ffi::wxDateTime_ParseISODate(self.as_ptr(), date)
}
}
fn parse_iso_time(&self, date: &str) -> bool {
unsafe {
let date = wx_string_from(date);
let date = WxString::from(date);
let date = date.as_ptr();
ffi::wxDateTime_ParseISOTime(self.as_ptr(), date)
}
}
fn parse_rfc822_date(&self, date: &str, end: *mut c_void) -> bool {
unsafe {
let date = wx_string_from(date);
let date = WxString::from(date);
let date = date.as_ptr();
ffi::wxDateTime_ParseRfc822Date(self.as_ptr(), date, end)
}
}
fn parse_time(&self, time: &str, end: *mut c_void) -> bool {
unsafe {
let time = wx_string_from(time);
let time = WxString::from(time);
let time = time.as_ptr();
ffi::wxDateTime_ParseTime(self.as_ptr(), time, end)
}
}
Expand Down
49 changes: 39 additions & 10 deletions wx-base/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::convert::TryInto;
use std::marker::PhantomData;
use std::mem;
use std::os::raw::{c_char, c_int, c_void};
use std::ptr;
use std::slice;
use std::str;

mod macros;

Expand Down Expand Up @@ -37,6 +38,7 @@ mod ffi {

// String
pub fn wxString_new(psz: *const c_uchar, nLength: usize) -> *mut c_void;
pub fn wxString_delete(self_: *mut c_void);
pub fn wxString_UTF8Data(self_: *mut c_void) -> UTF8Data;

// (wx)String::const_iterator
Expand Down Expand Up @@ -76,7 +78,10 @@ pub mod methods {

pub trait ArrayStringMethods: WxRustMethods {
fn add(&self, s: &str) {
unsafe { ffi::wxArrayString_Add(self.as_ptr(), wx_string_from(s)) }
unsafe {
let s = WxString::from(s);
ffi::wxArrayString_Add(self.as_ptr(), s.as_ptr())
}
}
}

Expand All @@ -94,7 +99,8 @@ pub mod methods {
fn parse_date(&self, date: &str) -> Option<usize> {
unsafe {
let end = StringConstIterator::new();
let date = wx_string_from(date);
let date = WxString::from(date);
let date = date.as_ptr();
if ffi::wxDateTime_ParseDate(self.as_ptr(), date, end.as_ptr()) {
Some(end.index_in(date))
} else {
Expand All @@ -105,15 +111,38 @@ pub mod methods {
}
}

pub fn from_wx_string(s: *mut c_void) -> String {
unsafe {
let utf8 = ffi::wxString_UTF8Data(s);
let len = utf8.length;
return String::from_raw_parts(utf8.data, len, len);
// wxString
pub struct WxString(*mut c_void);
impl WxString {
pub unsafe fn from_ptr(ptr: *mut c_void) -> Self {
WxString(ptr)
}
pub unsafe fn as_ptr(&self) -> *mut c_void {
return self.0;
}
pub fn to_str<'a>(&'a self) -> &'a str {
unsafe {
let utf8 = ffi::wxString_UTF8Data(self.as_ptr());
let len = utf8.length;
let slice = slice::from_raw_parts(utf8.data, len);
str::from_utf8_unchecked(slice)
}
}
}
pub unsafe fn wx_string_from(s: &str) -> *const c_void {
return ffi::wxString_new(s.as_ptr(), s.len());
impl From<WxString> for String {
fn from(s: WxString) -> Self {
s.to_str().to_owned()
}
}
impl From<&str> for WxString {
fn from(s: &str) -> Self {
unsafe { WxString(ffi::wxString_new(s.as_ptr(), s.len())) }
}
}
impl Drop for WxString {
fn drop(&mut self) {
unsafe { ffi::wxString_delete(self.0) }
}
}

// Rust closure to wx calablle function+param pair.
Expand Down
3 changes: 3 additions & 0 deletions wx-base/src/manual.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ void wxEvtHandler_Bind(wxEvtHandler *self, int eventType, void *aFn, void *aPara
wxString *wxString_new(const unsigned char *psz, const size_t nLength) {
return new wxString(psz, wxConvUTF8, nLength);
}
void wxString_delete(wxString *self) {
delete self;
}
UTF8Data wxString_UTF8Data(wxString *self) {
auto utf8 = self->ToUTF8();
return {
Expand Down
Loading

0 comments on commit 4b9a1fd

Please sign in to comment.