These are chat archives for rust-lang/rust

15th
Feb 2019
No equivalent
Tritone
@tritone11
Feb 15 11:47
Hi, I have a function that return a &'static str to a C program, and I try to convert a String to a str. However, it involves leaking the memory of the String. So, my C program result as some added strange characters at the end of the string coming from rust. Any clue about how to get around this?
Zakarum
@omni-viral
Feb 15 11:47
@tritone11 This is orthogonal
Strange characters you see because in rust strings are not null-terminated
That's why there is std::ffi::CString and std::ffi::CStr
std::ffi::CString will add \0 for you when created
Tritone
@tritone11
Feb 15 11:49
I tried to used CStr, I use it to read correctly the string coming from C, but if I try to use it as a response, C is unable to read it correctly
Zakarum
@omni-viral
Feb 15 11:50
How is your string returning function defined?
If you call it from C it should return *const c_char. And in C it should be extern char* funcname(yada-yada)
So you should get CStr and call as_ptr to get a pointer to return
Tritone
@tritone11
Feb 15 11:54
let signed_tx = a.as_ptr()
let c_string = CStr::from_ptr(signed_tx as *const i8) ;
println!("{:?}",c_string);
return c_string
this is what I am doing
it should be a long hexadecimal string, but C see is like this
signed_tx: P
this is how it is defined: extern char* foo(char *secret, char *path);
Zakarum
@omni-viral
Feb 15 11:58
You return &Cstr, but receive char*
Those are different types
Your rust function should return c_string.as_ptr(). I.e. *const i8
Tritone
@tritone11
Feb 15 12:03
if I try to do c_string.as_ptr()
I get
error: invalid conversion from ‘char’ to ‘unsigned char
on my C program
should I defined it as unsigned on c?
Zakarum
@omni-viral
Feb 15 12:06
No. CStr::as_ptr returns *const i8. Look elsewhere
Tritone
@tritone11
Feb 15 12:08
Probably my problem is that I am coming from a Vec<u8>
Zakarum
@omni-viral
Feb 15 12:11
If it is C compiler not happy then probably problem is in C code?
Tritone
@tritone11
Feb 15 12:16
Now it just hangs. when executing the function. I need to stop, keeping to do mistakes. Thanks for the suggestions @omni-viral , I am sure I will figure it out later rereading your messages
Zakarum
@omni-viral
Feb 15 12:29
@tritone11 Take a break and have some tea :)
Tritone
@tritone11
Feb 15 12:56
@omni-viral what are the risks of manually adding "\0" to the string? Like let s = my_string+"\0";
Zakarum
@omni-viral
Feb 15 12:57
my_string can already contain some '\0'
CString::new checks that
Tritone
@tritone11
Feb 15 12:58
thanks :)
Ingvar Stepanyan
@RReverser
Feb 15 12:58
well that's problem either way; but normally, adding \0 to constant strings is fine
Zakarum
@omni-viral
Feb 15 12:58
To literals - yes
Ingvar Stepanyan
@RReverser
Feb 15 12:58
this is what macros like https://crates.io/crates/cstr do btw
octave99
@octave99
Feb 15 17:29
In a dynamic trait dispatch &Foo Vs Box<Foo>, are both allocated over the heap or is it only the boxed version on heap and the former is over the stack?
Ingvar Stepanyan
@RReverser
Feb 15 17:30
one is just a reference (to anything, either on heap or on stack), while another is owned heap-allocated data
octave99
@octave99
Feb 15 17:33
@RReverser If I say &SomeStruct as &SomeTrait, its the SomeStruct that decides stack or heap, right? Which also means there won't be any performance penalty as against the Boxed version?
Ingvar Stepanyan
@RReverser
Feb 15 17:35
They just have different usecases, just like SomeStruct vs Box<SomeStruct>
If you want to give away ownership, use Box<dyn Foo>, if you want to take a reference, use &dyn Foo
octave99
@octave99
Feb 15 17:37
My use case is to store different structs to a vector, as per my knowledge one option is Enum and second is trait object. I am trying to figure out the most efficient way
Ingvar Stepanyan
@RReverser
Feb 15 17:37
Well then you likely need Box, unless you have a separate storage for the actual data
Otherwise what would reference point to?
octave99
@octave99
Feb 15 17:38
but then heap allocations won't bring overhead?
Ingvar Stepanyan
@RReverser
Feb 15 17:38
They do, sure
octave99
@octave99
Feb 15 17:38
Enum shouldn't be preferred then?
Ingvar Stepanyan
@RReverser
Feb 15 17:38
If you can use enum, that's better.
I thought you were still asking about &dyn ... vs Box<dyn ...>
octave99
@octave99
Feb 15 17:39
yeah, I did ask that to understand if reference can avoid heap
But from performance view, appears enum should be the most optimum way
Ingvar Stepanyan
@RReverser
Feb 15 17:40
yes, it can, but you still need to store the data somewhere else. in case with vector you likely don't have that option.
Denis Lisov
@tanriol
Feb 15 17:40
Enum may be a better way if the set of possible types is small or at least all are known in advance.
Don't know whether that's the case for you.
octave99
@octave99
Feb 15 17:41
@tanriol Yes, that's the case. I have limited pre-defined structs
Denis Lisov
@tanriol
Feb 15 17:43
There might be other cases that are suboptimal for a enum -- for example, if these structs have vastly different sizes -- but in general enum should probably be faster.
tsoernes
@tsoernes
Feb 15 18:07
is it possible to use trait constants in the default implementation?
pub trait Planet {
    const ORBITAL_SECS: f64;
    fn years_during(d: &Duration) -> f64 {
        (d.seconds as f64) / ORBITAL_SECS
    }
}
cannot find value ORBITAL_SECS in this scope (not found in this scope)
Ingvar Stepanyan
@RReverser
Feb 15 18:08
you need Self::
like with any associated consts
tsoernes
@tsoernes
Feb 15 18:09
Yes. That works. The compiler only hinted that you needed Self:: when I tried doing the same in a trait implementation