Re: [rust-dev] *c_char and *c_uchar

2014-05-10 Thread Valerii Hiora
Hi Christophe,

 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; }

  as_ptr() is a bad idea as there is no guarantee that Rust string is
null-terminated. It should be safer to use with_c_str like:

  filename.with_c_str(|c_str| unsafe {
sqlite3_open(c_str, ppDb)
  })
  
  More details here: 
  
http://static.rust-lang.org/doc/master/std/c_str/trait.ToCStr.html#method.with_c_str

 Now, suppose i use 
 extern { fn sqlite3_errmsg(pDb : *mut ()) - *c_uchar; }
 
  I believe it actually should be 
  extern { fn sqlite3_errmsg(pDB: *mut()) - *c_char; }

  And for creating an owned string from it you can use
std::str::raw::from_c_str

  More details here:
  http://static.rust-lang.org/doc/master/std/str/raw/fn.from_c_str.html 

-- 

  Valerii
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] *c_char and *c_uchar

2014-05-10 Thread Vladimir Matveev
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