-
Notifications
You must be signed in to change notification settings - Fork 221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
simple function for loading messages? #47
Comments
Could you say what it is you're trying to do? If you're trying to read a serialized message, you probably want I must admit I'm having a little trouble figuring out how to return the message once it's parsed, due to lifetime issues, but if you just want to print it that shouldn't be a problem. |
I'm trying to interface between rust and python with a nice common binary format. Basically I need something that takes I couldn't quite figure out how to get this working with |
Unfortunately, we don't yet have a function that can conveniently do this without copying the data. We had some discussion and made some progress on this on issue #25. If you're willing to copy the data, then |
Something like this should work: fn foo(mut buffer: &[u8]) -> capnp::Result<capnp::OwnedSpaceMessageReader> {
capnp::serialize::read_message(&mut buffer, capnp::ReaderOptions::new())
} |
Oh, I think you mean capnp::serialize::read_message(&mut Cursor::new(&mut buffer), capnp::ReaderOptions::new()) since Also, is there a way to return a Eg:
|
One way to go about this might be to implement a container type, like this pub struct OwnedMessage<T> {
phantom_data: ::std::marker::PhantomData<T>,
message: ::capnp::OwnedSpaceMessageReader,
}
impl <'a, T> OwnedMessage <T> where T: ::capnp::traits::FromPointerReader<'a> {
pub fn get(&'a self) -> ::capnp::Result<T> {
use capnp::MessageReader;
self.message.get_root()
}
} You could then return a |
Thanks for the suggestions! Oddly this compiles
and this does not
with message
I haven't quite figured out this part
I put the code in that you mentioned but can't quite figure out what the body of foo is supposed to be.
in the end, i'm hoping to be able to write something like
|
Does this work? pub struct OwnedMessage<T> {
phantom_data: ::std::marker::PhantomData<T>,
message: ::capnp::OwnedSpaceMessageReader,
}
impl <T> OwnedMessage <T> {
pub fn new(message: ::capnp::OwnedSpaceMessageReader) -> OwnedMessage<T> {
OwnedMessage { phantom_data: ::std::marker::PhantomData, message: message}
}
}
impl <'a, T> OwnedMessage <T> where T: ::capnp::traits::FromPointerReader<'a> {
pub fn get(&'a self) -> ::capnp::Result<T> {
use capnp::MessageReader;
self.message.get_root()
}
}
fn foo(mut buffer: &[u8]) -> ::capnp::Result<OwnedMessage<date::Reader>> {
let message = try!(::capnp::serialize::read_message(&mut buffer, ::capnp::ReaderOptions::new()));
return Ok(OwnedMessage::new(message));
} |
Hm. I think there could be some lifetime issues with what I just suggested. Things will probably work out better if we forget about trying to make pub struct OwnedDateMessage {
message: ::capnp::OwnedSpaceMessageReader,
}
impl OwnedDateMessage {
pub fn get<'a>(&'a self) -> ::capnp::Result<date::Reader<'a>> {
use capnp::MessageReader;
self.message.get_root()
}
} |
(I think my original suggestion with the generic |
This is what I'm using now and it compiles/runs:
Then I'm using it as |
Your suggestion worked, thanks! Now I just need to figure out how to write out to a
|
Thanks for all of your help, my final program is #[repr(C)]
pub struct bytes_output {
values : *const u8,
len : usize,
}
#[no_mangle]
pub extern fn capnp_ex(external_data: *const u8, data_len : *const size_t) -> bytes_output {
let buf : &[u8] = unsafe{ slice::from_raw_parts(external_data, data_len as usize) };
let x = foo(buf).unwrap();
let y = x.get().unwrap();
println!("capnproto year read! {:?}", y.get_year());
let mut message = MallocMessageBuilder::new_default();
{
let mut out_dt = message.init_root::<date::Builder>();
out_dt.set_year(y.get_year() + 1);
out_dt.set_month(1);
out_dt.set_day(1);
}
let mut out_buf : Vec<u8> = Vec::new();
capnp::serialize::write_message( &mut out_buf, &message );
bytes_output {
values : out_buf.as_ptr(),
len : out_buf.len(),
}
} and the python that calls it import cffi
import capnp
#setup ffi
ffi = cffi.FFI()
ffi.cdef('''
typedef struct {
char* values;
size_t len;
} bytes_output;
bytes_output capnp_ex(char*, size_t);
''')
lib = ffi.dlopen("./target/release/libtest.so")
# setup capnp
capnp.remove_import_hook()
example = capnp.load('schema/example.capnp')
mydate = example.Date.new_message(year=2015, month=5, day=31)
mydatebytes = mydate.to_bytes()
myresp = lib.capnp_ex(ffi.new('char[]', mydatebytes), len(mydatebytes))
def out_iter(resp):
for i in range(resp.len):
yield resp.values[i]
print(myresp)
with open('tmp.bin','wb') as outf:
for byte in out_iter(myresp):
outf.write(byte) # must be a better way to do this..
with open('tmp.bin', 'rb') as inf:
myrespdate = example.Date.read( inf )
print(myrespdate) for some reason the python capnp implementation relies on files quite a bit and I couldn't find a way around using files. |
I think this could be great for python (and other) FFI so I have been trying to figure out how to load
&[u8]
into an actual object. This is what I have so far but I think it's probably misguided.Any tips? Perhaps something to do with
read_message
? I couldn't figure it out from the examplesThe text was updated successfully, but these errors were encountered: