rust


Caught between a lifetime and an FFI place


I am caught between two different issues/bugs, and can't come up with a decent solution. Any help would be greatly appreciated
Context, FFI, and calling a lot of C functions, and wrapping C types in rust structs.
The first problem is ICE: this path should not cause illegal move.
This is forcing me to do all my struct-wrapping using & references as in:
pub struct CassResult<'a> {
result:&'a cql_ffi::CassResult
}
Instead of the simpler, and preferable:
pub struct CassResult {
result:cql_ffi::CassResult
}
Otherwise code like:
pub fn first_row(&self) -> Result<CassRow,CassError> {unsafe{
Ok(CassRow{row:*cql_ffi::cass_result_first_row(self.result)})
}}
Will result in:
error: internal compiler error: this path should not cause illegal move
Ok(CassRow{row:*cql_ffi::cass_result_first_row(self.result)})
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
So, I go ahead and wrap everything using lifetime managed references, and all is not-horrible until I try to implement an iterator. At which point I see no way around this problem.
method next has an incompatible type for trait: expected concrete lifetime, found bound lifetime parameter
So given those two conflicting issues, I am totally stuck and can't find any way to implement a proper rust iterator around a FFI iterator-like construct.
Edit: With Shep's suggestion, I get:
pub struct CassResult {
pub result:cql_ffi::CassResult
}
and
pub fn get_result(&mut future:future) -> Option<CassResult> {unsafe{
let result:&cql_ffi::CassResult = &*cql_ffi::cass_future_get_result(&mut future.future);
Some(CassResult{result:*result})
}}
but then get:
error: cannot move out of borrowed content
Some(CassResult{result:*result}
Is there any way to make that pattern work? It's repeated all over this FFI wrapping code.
Only a partial answer: use the "streaming iterator" trait and macro.
I have had a similar problem making Rust bindings around the C mysql API. The result is code like this, instead of native for syntax:
let query = format!("SELECT id_y, value FROM table_x WHERE id = {}", id_x);
let res = try!(db::run_query(&query));
streaming_for!( row, res.into_iter(), {
let id_y: usize = try!(row.convert::<usize>(0));
let value: f64 = try!(row.convert::<f64>(1));
});
Here res holds the result and frees memory on drop. The lifetime of row is tied to res:
/// Res has an attached lifetime to guard an internal pointer.
struct Res<'a>{ p: *mut c_void }
/// Wrapper created by into_iter()
struct ResMoveIter<'a>{ res: Res<'a> }
impl<'a> /*StreamingIterator<'a, Row<'a>> for*/ ResMoveIter<'a>{
/// Get the next row, or None if no more rows
pub fn next(&'a mut self) -> Option<Row<'a>>{
...
}
}
#[unsafe_destructor]
impl<'a> Drop for Res<'a>{
fn drop(&mut self){
...
}
}
To answer my own question. The only decent answer was a way around the original ICE, but as thepowersgang comments, the correct way to do this now is to use :std::ptr::read, so using that approach, no ICE, and hopefully progress.

Related Links

Copy files to the target directory after build
Is it ok to return in main?
Why is this trait/implementation incompatible - bound lifetime vs concrete lifetime
Cannot move out of `req` because it is borrowed
remove duplicates from vector of custom struct
error with % operator inside closure
How can I open a file with the standard text editor?
How to use multiple variables in routes with Nickel?
sdl2-sys won't compile - could not exec the linker: No such file or directory
Cannot borrow as mutable more than once at a time in one code - but can in another very similar
Forcing a move for an implemented `Copy` type
When do I need to specify explicit lifetimes in Rust?
cannot borrow `self.x` as immutable because `*self` is also borrowed as mutable
Getting sequence of bytes (u8) from a char
How does the lifetime work on constant strings?
Conditionally compile only one module at a time

Categories

HOME
verification
yaml
yii
tabs
dronekit-python
nsis
google-webmaster-tools
elk-stack
flurry
ontology
turbojpeg
cocotb
yahoo
azure-graph-api
nexus3
amazon-emr
fbloginview
createjs
multi-step
global-variables
hidden
playframework-2.0
scala-ide
gmp
bosun
mime-types
device
chronicle-queue
window-managers
uri
basic-authentication
phpstorm-2016.1
instructions
windows2012
nest
testlink
jade4j
ms-solver-foundation
django-smart-selects
task-parallel-library
oauth2
grunt-contrib-watch
get-event-store
expandablelistview
doctrine-extensions
realstudio
tinyioc
django-static-precompiler
karabiner
openstack-glance
visual-format-language
sequence-diagram
ltrace
nrf51
rational-performance-test
jpda
dpkg
piping
bbc-micro
gnucash
node-glob
maximize
distributed-cache
mercurial-extension
vimperator
wepay
linuxbrew
stack-smash
google-maps-api-2
mousehover
http.client
canopy
kotlin-android-extensions
accessory
screwturn
application-blocks
strcmp
coalesce
apportable
xs
dynamic-rdlc-generation
html-frames
significant-digits
coordinate
kaazing
exponent
fbml
dip
mygeneration
tessellation
resharper-5.0
browser-based
data-retrieval
rtti

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App