2

This is from an OpenCL tutorial. I have:

void* args[4] = {(void*)5, (void*)123, NULL, NULL}; 
cl_mem mem_list[2] = {mem_d1, mem_d2}; // mem_d1 and mem_d2 are cl_mem objects
void* args_mem_loc[2] = {&args[2], &args[3]};
status = clEnqueueNativeKernel(*queue, nativeKernel, args, 4, 2, mem_list, args_mem_loc, 0, NULL, NULL); // http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clEnqueueNativeKernel.html

I keep getting compiler error (on the line with status = clEnqueueNativeKernel(*queue... the parameter it is talking about is args_mem_loc).

error C2664: 'clEnqueueNativeKernel' : cannot convert parameter 7 from 'void *[2]' to 'const void **'

args_mem_loc is a void pointer to an array of void pointers and all of the variables it uses are created on the stack (right? im pretty sure). So why does the compiler consider it to be void* [2]?

user1873073
  • 3,580
  • 5
  • 46
  • 81
  • 1
    A pointer to an array and a pointer to another pointer are not the same thing. You need to make args_mem_loc a second pointer instead of an array. – Tricky12 Aug 21 '13 at 17:54
  • 1
    Maybe I am missing something here, but array T[] decays to T*, so void*[] decays to void**, so it should work? – Neil Kirk Aug 21 '13 at 17:58
  • &args_mem_loc[0] gets it closer but i am still getting an error for it not being constant ----- cannot convert parameter 7 from 'void **' to 'const void **' – user1873073 Aug 21 '13 at 18:03
  • Nice explanation here: http://c-faq.com/ansi/constmismatch.html – Brent Bradburn Aug 21 '13 at 19:10

2 Answers2

3

This:

void* args_mem_loc[2] = {&args[2], &args[3]};

implicitly converts to this:

void **

which is not implicitly convertible to this:

const void **

Because you could then assign a const void * to a void * and break const correctness.

The compiler says args_mem_loc is a void *[2] because that's what it is. If you want to pass down an array that can be implicitly converted to const void **, declare args_mem_loc as const void *arg_mem_loc[2]= {...};.

Incidentally, the const void ** parameters to that function should be const void * const *; in that case the implicit conversion would work. That would indicate that the function will not modify args_mem_loc because it would be illegal to assign through that pointer, and the implicit conversion would therefore be allowed.

MSN
  • 53,214
  • 7
  • 75
  • 105
1

When you have a pointer to an array, such as void* args_mem_loc[2] it means that you have a pointer pointing to an array of pointers, not another pointer itself. So essentially, you would need to use the following to pass args_mem_loc in as a pointer to a pointer:

&args_mem_loc[0]

or

&args_mem_loc[1]

You would then have a pointer (from the void*) pointing to another pointer (what is in each slot of the array).

Tricky12
  • 6,752
  • 1
  • 27
  • 35
  • 1
    the final answer was: const void* args[4] = {(void*)5, (void*)123, NULL, NULL}; cl_mem mem_list[2] = {mem_d1, mem_d2}; const void* args_mem_loc[2] = {&args[2], &args[3]}; status = clEnqueueNativeKernel(*queue, nativeKernel, args, 4, 2, mem_list, &args_mem_loc[0], 0, NULL, NULL); – user1873073 Aug 21 '13 at 18:19