Skip to content

Commit 4282a24

Browse files
committed
Add a simple refcounted boxed type
This is basically an Arc<Option<String>>
1 parent 7ed86ae commit 4282a24

File tree

10 files changed

+201
-3
lines changed

10 files changed

+201
-3
lines changed

Makefile

+6-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ HEADERS = \
33
include/ex/foo.h \
44
include/ex/bar.h \
55
include/ex/nameable.h \
6-
include/ex/rstring.h
6+
include/ex/rstring.h \
7+
include/ex/shared-rstring.h \
78

89
RUST_SOURCES = \
910
src/lib.rs \
@@ -18,7 +19,10 @@ RUST_SOURCES = \
1819
src/nameable/mod.rs \
1920
src/rstring/ffi.rs \
2021
src/rstring/imp.rs \
21-
src/rstring/mod.rs
22+
src/rstring/mod.rs \
23+
src/shared_rstring/ffi.rs \
24+
src/shared_rstring/imp.rs \
25+
src/shared_rstring/mod.rs
2226

2327
all: Ex-0.1.gir Ex-0.1.typelib
2428

include/ex/ex.h

+1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
#include "bar.h"
66
#include "nameable.h"
77
#include "rstring.h"
8+
#include "shared-rstring.h"
89

910
#endif /* __EX_H__ */

include/ex/shared-rstring.h

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef __EX_SHARED_RSTRING_H__
2+
#define __EX_SHARED_RSTRING_H__
3+
4+
#include <glib-object.h>
5+
6+
G_BEGIN_DECLS
7+
8+
#define EX_TYPE_SHARED_RSTRING (ex_shared_rstring_get_type())
9+
10+
typedef struct _ExSharedRString ExSharedRString;
11+
12+
GType ex_shared_rstring_get_type (void);
13+
14+
ExSharedRString * ex_shared_rstring_new (const gchar * s);
15+
ExSharedRString * ex_shared_rstring_ref (ExSharedRString * shared_rstring);
16+
void ex_shared_rstring_unref (ExSharedRString * shared_rstring);
17+
gchar * ex_shared_rstring_get (ExSharedRString * shared_rstring);
18+
19+
G_END_DECLS
20+
21+
#endif /* __EX_SHARED_RSTRING_H__ */

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ pub mod foo;
1616
pub mod bar;
1717
pub mod nameable;
1818
pub mod rstring;
19+
pub mod shared_rstring;

src/rstring/imp.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl RString {
2020
}
2121

2222
fn get(&self) -> Option<String> {
23-
self.0.as_ref().map(|s| s.clone())
23+
self.0.clone()
2424
}
2525

2626
fn set(&mut self, s: Option<String>) {

src/shared_rstring/ffi.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use glib_ffi;
2+
use gobject_ffi;
3+
use libc::{c_char, c_void};
4+
5+
// Opaque struct
6+
#[repr(C)]
7+
pub struct SharedRString(c_void);
8+
9+
extern "C" {
10+
pub fn ex_shared_rstring_get_type() -> glib_ffi::GType;
11+
12+
pub fn ex_shared_rstring_new(s: *const c_char) -> *const SharedRString;
13+
pub fn ex_shared_rstring_ref(shared_rstring: *mut SharedRString) -> *mut RString;
14+
pub fn ex_shared_rstring_unref(shared_rstring: *mut SharedRString);
15+
16+
pub fn ex_shared_rstring_get(shared_rstring: *mut SharedRString) -> *mut c_char;
17+
}

src/shared_rstring/imp.rs

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use glib_ffi;
2+
use gobject_ffi;
3+
4+
use std::ffi::CString;
5+
use std::sync::{Once, ONCE_INIT};
6+
use std::mem;
7+
use std::sync::Arc;
8+
9+
use glib::translate::{from_glib_none, ToGlibPtr};
10+
11+
use libc::{c_char, c_void};
12+
13+
// No #[repr(C)] here as we export it as an opaque struct
14+
// If it was not opaque, it must be #[repr(C)]
15+
pub struct SharedRString(Option<String>);
16+
17+
impl SharedRString {
18+
fn new(s: Option<String>) -> Arc<SharedRString> {
19+
Arc::new(SharedRString(s))
20+
}
21+
22+
// FIXME: This could borrow the &str in theory!
23+
fn get(&self) -> Option<String> {
24+
self.0.clone()
25+
}
26+
}
27+
28+
//
29+
// Public C functions below
30+
//
31+
#[no_mangle]
32+
pub unsafe extern "C" fn ex_shared_rstring_new(s: *const c_char) -> *mut SharedRString {
33+
callback_guard!();
34+
35+
let s = SharedRString::new(from_glib_none(s));
36+
Arc::into_raw(s) as *mut _
37+
}
38+
39+
#[no_mangle]
40+
pub unsafe extern "C" fn ex_shared_rstring_ref(
41+
shared_rstring: *mut SharedRString,
42+
) -> *mut SharedRString {
43+
callback_guard!();
44+
45+
let shared_rstring = Arc::from_raw(shared_rstring);
46+
let s = shared_rstring.clone();
47+
48+
// Forget it and keep it alive, we will still need it later
49+
let _ = Arc::into_raw(shared_rstring);
50+
51+
Arc::into_raw(s) as *mut _
52+
}
53+
54+
#[no_mangle]
55+
pub unsafe extern "C" fn ex_shared_rstring_unref(shared_rstring: *mut SharedRString) {
56+
callback_guard!();
57+
58+
let _ = Arc::from_raw(shared_rstring);
59+
}
60+
61+
#[no_mangle]
62+
pub unsafe extern "C" fn ex_shared_rstring_get(shared_rstring: *mut SharedRString) -> *mut c_char {
63+
callback_guard!();
64+
65+
let shared_rstring = &*shared_rstring;
66+
// FIXME: This could borrow the &str in theory!
67+
shared_rstring.get().to_glib_full()
68+
}
69+
70+
// GObject glue
71+
#[no_mangle]
72+
pub unsafe extern "C" fn ex_shared_rstring_get_type() -> glib_ffi::GType {
73+
callback_guard!();
74+
75+
static mut TYPE: glib_ffi::GType = gobject_ffi::G_TYPE_INVALID;
76+
static ONCE: Once = ONCE_INIT;
77+
78+
ONCE.call_once(|| {
79+
let type_name = CString::new("ExSharedRString").unwrap();
80+
81+
TYPE = gobject_ffi::g_boxed_type_register_static(
82+
type_name.as_ptr(),
83+
Some(mem::transmute(ex_shared_rstring_ref as *const c_void)),
84+
Some(mem::transmute(ex_shared_rstring_ref as *const c_void)),
85+
);
86+
87+
});
88+
89+
TYPE
90+
}

src/shared_rstring/mod.rs

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#[cfg(not(feature = "bindings"))]
2+
pub mod imp;
3+
4+
#[cfg(feature = "bindings")]
5+
mod ffi;
6+
#[cfg(feature = "bindings")]
7+
pub mod imp {
8+
pub use foo::ffi::*;
9+
}
10+
11+
use glib_ffi;
12+
use gobject_ffi;
13+
14+
use glib::translate::*;
15+
16+
use std::ptr;
17+
use std::mem;
18+
19+
glib_wrapper! {
20+
pub struct SharedRString(Shared<imp::SharedRString>);
21+
22+
match fn {
23+
ref => |ptr| imp::ex_shared_rstring_ref(ptr),
24+
unref => |ptr| imp::ex_shared_rstring_unref(ptr),
25+
get_type => || imp::ex_shared_rstring_get_type(),
26+
}
27+
}
28+
29+
impl SharedRString {
30+
pub fn new(s: Option<&str>) -> SharedRString {
31+
unsafe { from_glib_full(imp::ex_shared_rstring_new(s.to_glib_none().0)) }
32+
}
33+
34+
// FIXME: This could borrow the &str in theory!
35+
pub fn get(&self) -> Option<String> {
36+
unsafe { from_glib_full(imp::ex_shared_rstring_get(self.to_glib_none().0)) }
37+
}
38+
}
39+
40+
#[cfg(test)]
41+
mod tests {
42+
use super::*;
43+
44+
#[test]
45+
fn test_new() {
46+
let s = SharedRString::new(Some("bla"));
47+
assert_eq!(s.get(), Some("bla".into()));
48+
49+
let mut s2 = s.clone();
50+
assert_eq!(s.get(), Some("bla".into()));
51+
}
52+
}

test.js

+7
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,10 @@ print("rstring: " + s.get());
3737
let s2 = s.copy();
3838
s2.set("something else");
3939
print("rstring2: " + s2.get());
40+
41+
let s = new Ex.SharedRString("something");
42+
print("shared rstring: " + s.get());
43+
let s2 = s.ref();
44+
print("shared rstring2: " + s2.get());
45+
46+

test.py

+5
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,8 @@ def on_incremented(obj, val, inc):
3737
s2 = s.copy()
3838
s2.set("something else")
3939
print("rstring 2: " + str(s2.get()))
40+
41+
s = Ex.SharedRString.new("something")
42+
print("shared rstring: " + str(s.get()))
43+
s2 = s.ref()
44+
print("shared rstring 2: " + str(s2.get()))

0 commit comments

Comments
 (0)