-
Notifications
You must be signed in to change notification settings - Fork 375
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
Revise the FFI chapters #190
Revise the FFI chapters #190
Conversation
@jhwgh1968 how do you think I should approach the I feel like the example is too contrived to show how you might use fn mylib_log(msg: &str) {
let msg: String = msg.to_owned();
crate::log(&msg, ...);
} ... which isn't really code that people would write. From my experience you don't really use The only example I can think of is when you need to store the string somewhere and keep it around after the function ends, but even then I'd use The |
There are actually two orthogonal concepts that we'll want to address in the error handling chapter. One is returning the equivalent of Rust's For example, how would write FFI bindings for something like this? fn parse_elf(filename: *const c_str) -> Result<ElfBinary, ParseError>;
struct ElfBinary { ... }
enum ParseError { ... } Some possible solutions are: typedef struct ElfBinary ElfBinary;
// null on parse failed
ElfBinary *parse_elf(const char *filename);
// out parameters and result enum
typedef enum ParseResult {
OK = 0,
...
} ParseResult;
ParseResult parse_elf(const char *filename, ElfBinary **parsed);
// out parameters and boolean return
boolean parse_elf(const char *filename, ElfBinary **parsed);
// errno-style and null
extern int errno;
const char *last_error_msg();
ElfBinary *parse_elf(const char *filename);
// everything is out parameters
typedef enum ParseResult {
OK = 0,
...
} ParseResult;
void parse_elf(const char *filename, ElfBinary **parsed, ParseResult *result); |
It is a little contrived, but I could not do a good translation of what I had. My goal with that alternative was to illustrate a thought process I actually had in the beginning: always copy all pointers to a Rust-owned value ASAP, and then never touch the pointers again, no matter what type they were. That is what I wanted to discourage.
I had code that did a bunch of pointer arithmetic, so I put it in. But that was because I had C code which did that, and it stayed around for quite some time before I completely rewrote it. I agree that most Rust programmers wouldn't think of something that backwards, and it might not be worth putting in. In fact, your snippet seems like a good thing to replace my alternative with: "if you really want an owned one, use this. Don't do pointer arithmetic or null byte termination yourself, because it's error prone, and this takes care of it."
I tried to suggest (and wasn't very clear) that the "value" was what was returned by
The pattern I wrote would say one of two things: if it's opaque, return it as a pointer. If it's transparent, use an out parameter and an integer code (either non/zero, or an error code number). /* elfbin.h */
// if transparent
int elf_bin_new(const char* filename, **ElfBinary out_elf);
// if opaque, returns NULL pointer on error
*ElfBinary elf_bin_new(const char *filename);
// either way, you can get more information about the error message with this
//
// pass a pointer to an ElfBinary that was constructed to get the last error from its call.
// pass NULL pointer in order to get the last error from a global call, like "new."
const char *elf_bin_error(*ElfBinary e); Suffice it to say, I'm trying to avoid doing what some libraries do, which is to overwrite |
This is quite nice, we want to explain it in the book? Anyway here you are talking about another part of the book (error handling), which is not really related to this PR, right? |
I was talking about what motivated a previous example in Accepting Strings, which in retrospect was very convoluted. It is a general idea, but Accepting Strings was where I put it, because that's where it was most notable in my early code. Strings come in as I do not know whether it is worth a mention in Accepting Strings or not, if it is moved to a general principle. I would approve this PR either way. |
@jhwgh1968 @Michael-F-Bryan Hey you both, any updates on this? Asking because we're probably changing the |
I'm going to close this PR because I don't have the time to complete it and didn't really want to invest much more than that initial review. |
Hi Michael, I reopen this and I assign it to me. I will continue the work you have started :) |
Merged this! If you think something valuable from the above comments needs to be discussed further, please open an issue or another PR! |
This is a continuation of #106 which addresses some of the items pointed out in the review.
Fixes #171.