Home > Net >  How to pass a static array of custom_object type as a parameter to another custom object in C?
How to pass a static array of custom_object type as a parameter to another custom object in C?

Time:10-29

Here are my custom objects:

typedef struct sem_holder
{
    sem_t *writer_sem;
    sem_t *reader_sem;
} sem_holder;

typedef struct worker_arg
{
    unsigned int nsegments;
    size_t segsize;
    sem_holder *sems;
} worker_arg;

Here is my code, where I pass a &sems argument to the custom objects above:

  sem_holder *sems[nsegments];
  sem_holder sems_obj;
  char sem_write_name[21];
  char sem_read_name[21];
  sem_t *writer_sem;
  sem_t *reader_sem;

  ftruncate(DATA_CHANNEL_ID, segsize * nsegments);
  for (int i = 0; i < nsegments; i  )
  {
    // Map subsection of data-channel to an array in proxy's virtual memory
    // processes[i] = mmap(NULL, sizeof(segsize), PROT_READ | PROT_WRITE, MAP_SHARED, 
DATA_CHANNEL_ID, i * segsize);

    // Dynamically create reader and writer names
    snprintf(sem_write_name, 21, "%dw", i);
    snprintf(sem_read_name, 21, "%dr", i);

    // Create a likewise array for semaphores
    writer_sem = sem_open(sem_write_name, O_CREAT, 0660, 0);
    if (writer_sem == SEM_FAILED)
      printf("FAILED\n");
    sems_obj.writer_sem = writer_sem;

    reader_sem = sem_open(sem_read_name, O_CREAT, 0660, 0);
    if (reader_sem == SEM_FAILED)
      printf("FAILED\n");
    sems_obj.reader_sem = reader_sem;

    sems[i] = &sems_obj;
  }

  // Initialize worker arg
  worker_arg worker_arg = {.nsegments = nsegments, .segsize = segsize, .sems = &sems};

When I do &sems, I get this error:

webproxy.c: In function ‘main’:
webproxy.c:209:80: error: initialization of ‘sem_holder *’ {aka ‘struct sem_holder *’} from incompatible pointer type ‘sem_holder * (*)[(sizetype)(nsegments)]’ [-Werror=incompatible-pointer-types]
  209 | egments, .segsize = segsize, .sems = &sems};
      |  

When I do just sems, I get this error:

webproxy.c: In function ‘main’:
webproxy.c:209:80: error: initialization of ‘sem_holder *’ {aka ‘struct sem_holder *’} from incompatible pointer type ‘sem_holder **’ {aka ‘struct sem_holder **’} [-Werror=incompatible-pointer-types]
  209 | segsize = segsize, .sems = sems};
      |  

Seems it is likely an issue with the way I declare my worker_arg sems parameter. I am just uncertain how I would store this sem_holder array in my worker_arg object. I figured passing a pointer to the object would work but it does not seem to. Any ideas or thought processes that could help?


edit, here is my updated code. I am able to pass the sems object now which is good. The value of these semaphores is always 0 though, which is not what I declared it as in sem_open. Clearly I am a novice in C

  // char *processes[nsegments];
  sem_holder sems[nsegments];
  char sem_write_name[21];
  char sem_read_name[21];
  sem_t *writer_sem;
  sem_t *reader_sem;

  ftruncate(DATA_CHANNEL_ID, segsize * nsegments);
  for (int i = 0; i < nsegments; i  )
  {
    // Map subsection of data-channel to an array in proxy's virtual memory
    // processes[i] = mmap(NULL, sizeof(segsize), PROT_READ | PROT_WRITE, MAP_SHARED, DATA_CHANNEL_ID, i * segsize);

    // Dynamically create reader and writer names
    snprintf(sem_write_name, 21, "%dw", i);
    snprintf(sem_read_name, 21, "%dr", i);

    // Create a likewise array for semaphores
    writer_sem = sem_open(sem_write_name, O_CREAT, 0660, 10);
    if (writer_sem == SEM_FAILED)
      printf("FAILED\n");
    sems[i].writer_sem = writer_sem;

    reader_sem = sem_open(sem_read_name, O_CREAT, 0660, 10);
    if (reader_sem == SEM_FAILED)
      printf("FAILED\n");
    sems[i].reader_sem = reader_sem;
  }

  // Initialize worker arg
  worker_arg worker_arg = {.nsegments = nsegments, .segsize = segsize, .sems = sems};

CodePudding user response:

You declared sems as sem_holder *sems[nsegments]; which means that sems is an array of pointers to sem_holder structures.

What you want is a simple array so you can declare it like this:

sem_holder sems[nsegments];

The compiler indeed tells you that the pointers are incompatible, because what you are doing is basically the following:

int* p;
int* pp;

p = pp

CodePudding user response:

This ...

typedef struct worker_arg
{
    unsigned int nsegments;
    size_t segsize;
    sem_holder *sems;
} worker_arg;

... declares member worker_arg.sems as a pointer to a sem_holder. That can accommodate an array in the sense that the pointed-to sem_holder can be the first in an array of such, and the others can then be accessed through the same pointer.

On the other hand, this ...

  sem_holder *sems[nsegments];

... declares sems as an array of pointers to sem_holder. Any one element of that array could be assigned to a worker_arg.sems, but that would not provide access to the other elements of sems. The type of this sems array does not seem to be compatible with what you want to do.

Note also that you set every member of sems to the same value, &sems_obj. You modify the object that they all point to on each iteration of the loop, which is surely not what you really want to do.

It looks like you want this ...

      sem_holder sems[nsegments];  // array of sem_holder, not of pointers
      // sem_holder sems_obj;      // not needed and probably not wanted

... then in your loop, replace references to sems_obj with sems[i].

After that, this ...

  worker_arg worker_arg = {.nsegments = nsegments, .segsize = segsize, .sems = sems};

... will be type correct, and (more) semantically correct.

Do note, however, that the sem_holder array designated by sems lives only until the execution of the block in which it is defined terminates. That may be fine for you purposes, but if you need it to live longer then you need to dynamically allocate space (e.g. with malloc()) rather than using a variable-length array.

  •  Tags:  
  • c
  • Related