Hi!
First of all, if you are writing custom bindings to sqlite not only to
learn Rust, I'd suggest using already existing bindings [1]. That way
you probably won't have to deal with low-level C integration stuff.
However, if you want to learn how to write C bindings, you should
probably start with reading an official tutorial [2] on foreign
function interface. That way you will learn that Rust strings are not
C-compatible, they are not terminated by zero byte, so you can't get a
pointer from a string and pass it to a C routine directly. In order to
properly convert str to *c_char you have to use various conversion
utilities, the most simple one being with_c_str() method:
let s = some_string;
let result = s.with_c_str(|char_ptr| {
// call C functions, char_ptr is a *c_char pointer
// after this block finishes, a buffer pointed to by char_ptr
will be freed
some_result
});
Here [3] is the relevant piece of documentation on C strings conversions.
Your second example is also incorrect. Converting C strings to static
slices is highly unsafe, for example, it will crash your program if
the string is not a valid UTF-8 sequence, not to mention lifetime
issues. There is a reason why it is placed in such inconvenient place
as `std::str::raw`. You shouldn't use it. Instead you should use
std::c_str::CString structure to wrap C strings. BTW, this structure
also forces you to think about ownership. I don't know much about
sqlite API, but if you're not supposed to free a string returned by
sqlite3_errmsg() function, you should create CString like this
CString::new(sqlite3_errmsg(*ppDb), false)
false means that this CString won't own the buffer and won't free it
when it goes out of scope.
When you have CString structure, you can get a string slice out of it
using as_str() method. This all is documented here [4].
[1]: https://github.com/linuxfood/rustsqlite.
[2]: http://static.rust-lang.org/doc/master/guide-ffi.html
[3]: http://static.rust-lang.org/doc/master/std/c_str/index.html
[4]: http://static.rust-lang.org/doc/master/std/c_str/struct.CString.html
2014-05-10 18:14 GMT+04:00 Christophe Pedretti christophe.pedre...@gmail.com:
Hi all,
i am writing a wrapper to an SQLite database.
If i use :
extern { fn sqlite3_open(filename: *c_char, ppDb : **mut ()) - c_int; }
i can not use :
let ppDb : **mut () = RawPtr::null();
unsafe { res=sqlite3_open(filename.as_ptr(), ppDb);
because as_ptr() returns an *u8 and c_char is a i8, so i have to use
extern { fn sqlite3_open(filename: *c_uchar, ppDb : **mut ()) - c_int; }
Now, suppose i use :
extern { fn sqlite3_errmsg(pDb : *mut ()) - *c_uchar; }
i can not use :
let mut desc=; { unsafe { desc =
c_str_to_static_slice(sqlite3_errmsg(*ppDb)); } }
because c_str_to_static_slice taks a *c_char (so an i8) as argument, so i
have to use
extern { fn sqlite3_errmsg(pDb : *mut ()) - *c_char; }
If the second example is quite logical, what about the first one ?
how to convert str - *c_char ?
thanks
--
Christophe
http://chris-pe.github.io/Rustic/
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev