4

I have a function in C:

void start_fun()
{
   // do something
}

I want to use pthread_create() to create a thread and the start routine is start_fun(), without modifing void start_fun(), how to get the function pointer to start_fun();

ratzip
  • 1,571
  • 7
  • 28
  • 53
  • `start_fun` *is* the pointer to `start_fun`. Although.. it isn't a function of the correct type. `pthread_create` wants a `void * (*f) (void *)`. – ArjunShankar Sep 11 '15 at 13:21

2 Answers2

6

If you write the function name start_fun without any parameters anywhere in your code, you will get a function pointer to that function.

However pthread_create expects a function of the format void* func (void*).

If rewriting the function isn't an option, you'll have to write a wrapper:

void* call_start_fun (void* dummy)
{
  (void)dummy;

  start_fun();

  return 0;
}

then pass call_start_fun to pthread_create:

pthread_create(&thread, NULL, call_start_fun, NULL);
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 2
    The function isn't of the correct type required by `pthread_create`. – ArjunShankar Sep 11 '15 at 13:23
  • @ArjunShankar Indeed, I've fixed the answer. Thank you. – Lundin Sep 11 '15 at 13:28
  • 2
    It's just a matter of style, but I would return `NULL` from `call_start_fun` – JeremyP Sep 11 '15 at 13:29
  • @JeremyP Doesn't matter since the result will be [any null pointer constant] casted to void* and the function will therefore always return the null pointer constant `(void*)0`. – Lundin Sep 11 '15 at 13:31
  • yes, but I got a error error: invalid conversion from 'int (*)()' to 'void* (*)(void*)' [-fpermissive] pthread_create(&thread_id, NULL, start_fun, NULL); – ratzip Sep 11 '15 at 13:32
  • @ratzip Then compile the above code instead, which solves the problem? – Lundin Sep 11 '15 at 13:34
  • no, I do not want to change the function of start_fun() – ratzip Sep 11 '15 at 13:35
  • @ratzip, the pthread start function *must* have the signature that both @Lundin and I specified. The signature of `pthread_create()` demands it, and your program has undefined behavior that likely involves crashing or memory corruption if you do not provide it. – John Bollinger Sep 11 '15 at 13:38
  • I try your code, I put the wrapper function as a public function in C++ class, then I got the following: error: cannot convert 'TryTest::call_start_fun' from type 'void* (TryTest::)(void*)' to type 'void* (*)(void*)' TryTest is the class name – ratzip Sep 11 '15 at 13:56
  • @ratzip You tagged your question C. And that problem is not likely related to the format of the function, but more likely because it is a C++ member function. You'll most likely have to declare the function as `static` in order to pass it to pthread_create. – Lundin Sep 11 '15 at 14:00
  • @ratzip [See this](http://stackoverflow.com/questions/1151582/pthread-function-from-a-class). – Lundin Sep 11 '15 at 14:03
  • @Lundin That's why I said it is just a matter of style, but I would use `NULL` rather than 0 because the return value is meant to be a pointer and you don't want people putting things like `return 1` because they assume it's like `main()` – JeremyP Sep 11 '15 at 14:08
  • @JeremyP That wouldn't work, `1` doesn't convert to `void *`. – unwind Sep 11 '15 at 14:11
  • @unwind Clang compiles it and emits a warning. – JeremyP Sep 11 '15 at 14:16
  • @JeremyP Oh. That's ... worse than I expected, but of course a warning is a pretty good indicator that "people" are doing something wrong. :) I'd use `NULL` too personally, btw. – unwind Sep 11 '15 at 14:18
  • @unwind The kind of person to use `return 1` when the function is meant to return a `void*` is also the kind of person who would ignore compiler warnings IMO :) – JeremyP Sep 11 '15 at 14:35
3

The function name, used as an expression, evaluates to a pointer to the named function. Thus, for instance:

pthread_t thread_id;
int result = pthread_create(&thread_id, NULL, start_fun, NULL);

HOWEVER, the start function you present does not have the correct signature, therefore using it as a pthread start function produces undefined behavior. The start function must have this signature:

void *start_fun(void *arg);

The function may ignore its argument and always return NULL, if appropriate, but it must be declared with both the argument and the return value (of those types).

John Bollinger
  • 160,171
  • 8
  • 81
  • 157