0

I have the following structs defined:

In gf.h:

typedef struct gfcrequest_t gfcrequest_t;

In gf.c:

typedef struct gfcrequest_t {
  struct sockaddr_in saddr;
  // ...
  char *path; // <---- get here
  gfstatus_t status;
  void (*writefunc)(void*, size_t, void *);
  // ...
} gfcrequest_t;

In gf_main.c

typedef struct wrequest_t {
  long int msg_type;
  char *message;
  gfcrequest_t *gfr; // <---- from here
} wrequest_t;

I want to be able to access the path member of the gfr pointer on an instance of wrequest_t.

I have the following:

wrequest_t *wrequest = malloc(sizeof(struct wrequest_t));
bzero(&wrequest, sizeof(wrequest));
gfcrequest_t *gfr = gfc_create(); // function returns a pointer to gfcrequest_t
// ... some pre-processing
wrequest->gfr = gfr; // pointer to pointer, is that correct?
// ... pass the wrequest to thread through message queue for processing

Then, in the thread I pop the request out of the queue and try to process it

  wrequest_t *wrequest;
  for (;;) {
    if (msgrcv(msg_id, &wrequest, size_wrequest, MSG_TYPE, 0) == -1) {
      perror("failed to receive work request");
      return NULL;
    }
    fprintf(stderr, "message is %s\n", wrequest->message);

    if (strncmp(wrequest->message,
                SHUTDOWN_MESSAGE, strlen(SHUTDOWN_MESSAGE)) == 0) {
      fprintf(stderr, "thread %lu is done\n", id);
      break;
    }

    fprintf(stderr, "thread %lu would process %s\n", id, wrequest->gfr->path); // <---------------------- this line doesn't work
  }

Compiler complains:\

cc -Wall --std=gnu99 -g -Wno-format-security   -c -o gfclient_download.o gfclient_download.c
gfclient_download.c: In function ‘work’:
gfclient_download.c:125:71: error: dereferencing pointer to incomplete type
     fprintf(stderr, "thread %lu would process %s\n", id, wrequest->gfr->path);

If I change the -> by the . it complains:

cc -Wall --std=gnu99 -g -Wno-format-security   -c -o gfclient_download.o gfclient_download.c
gfclient_download.c: In function ‘work’:
gfclient_download.c:125:71: error: request for member ‘path’ in something not a structure or union
     fprintf(stderr, "thread %lu would process %s\n", id, wrequest->gfr.path);

I'm a newbie in C as you can see... is there something obvious that I'm doing wrong? how to I get to path from the wrequest_t?

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
mimoralea
  • 9,590
  • 7
  • 58
  • 59
  • 2
    Put the full struct definition in the header file. "incomplete type" is referring to the `gfcrequest_t`, not the `char*`, since it can't see that type's members in your main file. – tehwalrus Jun 06 '15 at 23:07
  • Shut, is there a way to do it in the `.c` file? I'm not supposed to modify the header in the project, they will test my submission against their `.h`s – mimoralea Jun 06 '15 at 23:09
  • 1
    Then it is a private struct, and you are not allowed to read its contents. You can re-declare the entire struct in your C file, and it will work, but seriously, ask them to put it in the header file if that is an exported definition that other code files are allowed to see. – tehwalrus Jun 06 '15 at 23:11
  • Oh wow, I had no idea that you could do such a thing as a *private* structure in C. Thanks @tehwalrus I'm gonna have to work around this one. – mimoralea Jun 06 '15 at 23:12
  • it's not formally "private", since you can always dereference it and read the bytes... But unless you know how many bytes along your char* is at, you can't practically use it. – tehwalrus Jun 06 '15 at 23:14
  • Re-declaring is a good option. Let me try that first! – mimoralea Jun 06 '15 at 23:14
  • 1
    redeclaring is a *bad* option, as it means that your code will break if they change their definition and you forget to update yours. It *should* be in the header so that the definition is consistent for every compile, for the sake of good programming practise. As it said, it will *work* the other way, but it's not a good way to do things. – tehwalrus Jun 06 '15 at 23:16
  • why are you passing `&wrequest` to `bzero(&wrequest, sizeof(wrequest))` ? I believe you should remove the `&` since `wrequest` is the pointer to the allocated area you want to set to zero – Pynchia Jun 07 '15 at 00:13
  • 1
    You should write a function or two in `gf.c` that, when given a pointer to a `gfcrequest_t`, provide appropriate access to the path element. The functions should be declared in `gf.h` so that client source files can use them. 'Appropriate access' might mean returning a pointer to the element, or might mean that the calling code passes a buffer to the function into which the path is copied, or out of which the new value of the path is copied, or you might have pointers to allocated memory being swapped around, or … well, how many other inventive ways can you devise? – Jonathan Leffler Jun 07 '15 at 02:13
  • The key point is that code outside of `gf.c` cannot access the internals of the structure that is defined in `gf.c` unless you resort to dire and undesirable tricks such as including the source of `gf.c` in `gf_main.c` (but see [How to test a static function?](http://stackoverflow.com/questions/593414/) for an example of when that might be necessary). – Jonathan Leffler Jun 07 '15 at 02:15

0 Answers0