-1

I've been looking at this source code provided by developers of a library called libuv. In some of the example code they pass a function as a parameter for another function but none of the required parameters are passed. How are the parameters being filled out? The function I'm looking at is uv_fs_open.

Here is the link to the source (look around line 1000 for the function code): https://github.com/libuv/libuv/blob/202195c2f45ced200ccf880ff4502eee94f11ab5/src/unix/fs.c
Here is the example code:

int main() {
    loop = uv_default_loop();

    int r = uv_fs_open(loop, &open_req, path, O_RDONLY, S_IRUSR, open_cb);

    if (r) {
         fprintf(stderr, "Error at opening file: %s.\n", 
                uv_strerror(uv_last_error(loop)));
    }  

    uv_run(loop, UV_RUN_DEFAULT);

    return 0;
}

void open_cb(uv_fs_t* req) {
    int result = req->result;

    if (result == -1) {
        fprintf(stderr, "Error at opening file: %s.\n", 
                uv_strerror(uv_last_error(loop)));
    }  

    uv_fs_req_cleanup(req);
    uv_fs_read(loop, &read_req, result, buf, sizeof(buf), -1, read_cb);
}
rreichel
  • 794
  • 3
  • 9
  • 25
  • 3
    You know what a function pointer is, right ? It looks like the library uses function pointers to pass callback functions. – Paul R May 27 '15 at 19:04
  • `uv_fs_open` provides the parameters when *it* calls `open_cb` , which was provided as a function pointer parameter. – WhozCraig May 27 '15 at 19:05
  • Do you mean passing `open_cb` to `uv_fs_open` with no arguments? That's because you don't supply the arguments there, you are only telling `uv_fs_open` which function to call so that *it* can supply the arguments. – Weather Vane May 27 '15 at 19:07
  • Assuming you have little experience with c (by the nature of your question), you're much better off learning from actual learning material (books, tutorials, dedicated web sites) than from 1 of the more advanced pieces of code around the open source world. – Amit May 27 '15 at 19:07
  • @rreichel you deleted your comment, but the reason you don't see `uv_fs_open` doing anything with its argument `cb` (which was passed as `open_cb`) is that it is handled by the macro called `POST` – Weather Vane May 27 '15 at 19:14
  • Thanks for the quick response! I do know what a function pointer is but I'm moving to C from a Java background so its been slow going and not the first thing I thought of. Thanks again! @WeatherVane I did delete it - Accidentally added the comment too early - whoops. – rreichel May 27 '15 at 19:19
  • 2 years and a lot more CS schooling later I just wanted to thank all of you for your kind responses - I realize this was a newbie question and really appreciate the helpful constructive responses you all gave. Cheers! – rreichel May 09 '17 at 16:05

1 Answers1

2

libuv uses a pattern called callback baton for its async functions. The rationale is very simple: let's assume you want to do something asynchronously. So you pass a callback function as a function pointer to call when it's done. libuv's functions do their job asynchronously and call the function you specified when they're done.

However, if you have more than one places where you call these functions, once the callback is called, you are going to need to tell which request the callback is called for. That is the purpose of the baton object. In the case of your example code, that's the open_req variable (of the type uv_fs_t).

You can read more about libuv's file system operations here.

Venemo
  • 18,515
  • 13
  • 84
  • 125
  • Thanks @Venemo ! Heres a quick follow up: Where is the documentation for writing a callback to match the uv_fs_cb type? The API docs don't specify that – rreichel May 27 '15 at 19:23
  • @rreichel most of the time, those callbacks accept a single parameter whose type is a pointer to the *baton* object. I suggest you take a look at the libuv book: http://nikhilm.github.io/uvbook/ it also has a chapter on file system operations: http://nikhilm.github.io/uvbook/filesystem.html – Venemo May 27 '15 at 19:26