Croustibat
Croustibat

Reputation: 1

argument of type 'void* (...)(void*)' does not match 'void* (*)(void*)

I'm currently developing a bloc on GNU Radio and I want to use a thread. This thread is there to acquired data from a UDP socket so I can use it in my GNU Radio bloc. The "general work" function is the one that does all the signal and data processing.

The master source file is organized like this :

namespace gr {
    namespace adsb {

    out::sptr
    out::make()
    {
        return gnuradio::get_initial_sptr
        (new out_impl());
    }

    /*
     * UDP thread
     */
    void *task_UdpRx (void *arg)
    {
        while(true)
        {
            printf("Task UdpRx\n\r");
            usleep(500*1000);
        }
       pthread_exit(NULL);
    }

    /*
    * The private constructor
    */
    out_impl::out_impl()
        : gr::block("out",
                gr::io_signature::make(1, 1, sizeof(int)),
                gr::io_signature::make(1, 1, sizeof(char)))
    {
        pthread_t Thread_UdpRx;

        //Thread init
        if(pthread_create(&Thread_UdpRx, NULL, task_UdpRx, NULL))
        {
            err("Pthread error");
        }
        else
        {
            printf("UDP thread initialization completed\n\r");
        }
    }

    /*
    * Our virtual destructor.
    */
    out_impl::~out_impl()
    {
    }

    void out_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
    {
        ninput_items_required[0] = noutput_items;
    }

    int out_impl::general_work (int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
    {
        const int *in = (const int *) input_items[0];
        char *out = (char *) output_items[0];

        // Do <+signal processing+>
        for(int i = 0; i < noutput_items; i++)
        {
            printf("General work\n\r");
        }/* for < noutput_items */

        // Tell runtime system how many input items we consumed on
        // each input stream.
        consume_each (noutput_items);

        // Tell runtime system how many output items we produced.
        return noutput_items;
    } /* general work */

    } /* namespace adsb */
} /* namespace gr */`

The problem I get is that when I try to compile, I get this error :

In constructor ‘gr::adsb::out_impl::out_impl()’:
error: argument of type ‘void* (gr::adsb::out_impl::)(void*)’ does not match ‘void* (*)(void*)’

This error refers to the line and it concerns task_UdpRx :

if(pthread_create(&Thread_UdpRx, NULL, task_UdpRx, NULL))

Does anybody have any idea ?

Don't hesitate to ask for more details if needed. The code I've displayed is the shortest I could do in order for you to get the best understanding possible.

Thank you !

Upvotes: 0

Views: 2297

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 754530

You can't pass a pointer to member function to pthread_create().

You'll need a free function:

void *thread_start(void *object)
{
    gr::adsb::out_impl *object = reinterpret_cast<gr::adsb::out_impl *>(object);
    object.task_UpdRx(0);
    return 0;
}

or thereabouts, and you'll need to pass this function to pthread_create() and pass the this pointer as the data argument:

if (pthread_create(&Thread_UdpRx, NULL, thread_start, this))

I reserve the right to be misusing reinterpret_cast<>() — substitute the correct cast notation. I have reservations about starting the thread in the constructor, but this is the outline of a scheme that should work.


After the code update on 2014-06-25

The code is still not an MCVE. I can't copy it and compile it. There are many headers missing. The types out and out_impl are not defined/declared. Some of the GNU Radio inheritance stuff could probably be left out.

Here's my version of an MCVE. It isn't perfect because it doesn't reproduce your problem. It compiles cleanly on an Ubuntu 12.04 LTS derivative with GCC 4.9.0. It assumes you have a header <err.h> that defines a function err(). I'm not certain that the destructor is necessary for the MCVE (and removing it would eliminate another 5 lines or so).

Source

#include <cstdio>
#include <pthread.h>
#include <unistd.h>
#include <err.h>

namespace gr
{
    namespace adsb
    {
        class out_impl
        {
        public:
            out_impl();
            virtual ~out_impl();
        };

        void *task_UdpRx(void *arg)
        {
            while (true)
            {
                printf("Task UdpRx %p\n\r", arg);
                usleep(500*1000);
            }
            pthread_exit(NULL);
        }

        out_impl::out_impl()
        {
            pthread_t Thread_UdpRx;

            if (pthread_create(&Thread_UdpRx, NULL, task_UdpRx, NULL))
                err(1, "Pthread error");
            else
                printf("UDP thread initialization completed\n\r");
        }

        out_impl::~out_impl()
        {
        }

    }
}

Compilation

$ g++ --version
g++ (GCC) 4.9.0
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ make gr.o
g++ -g -O3 -std=c++11 -Wall -Wextra -Werror -c gr.cpp
$ nm -C -g gr.o
0000000000000010 T gr::adsb::task_UdpRx(void*)
0000000000000050 T gr::adsb::out_impl::out_impl()
0000000000000050 T gr::adsb::out_impl::out_impl()
0000000000000040 T gr::adsb::out_impl::~out_impl()
0000000000000000 T gr::adsb::out_impl::~out_impl()
0000000000000000 T gr::adsb::out_impl::~out_impl()
0000000000000000 V typeinfo for gr::adsb::out_impl
0000000000000000 V typeinfo name for gr::adsb::out_impl
                 U vtable for __cxxabiv1::__class_type_info
0000000000000000 V vtable for gr::adsb::out_impl
                 U operator delete(void*)
                 U err
                 U printf
                 U pthread_create
                 U usleep
$

Next steps

There are several ways that this Q&A can go from here:

  1. The question is abandoned or closed.
  2. You take the MCVE code and add stuff back until you get your original compilation error.
  3. You take your non-compiling code and remove stuff until you get to an MCVE from which you can remove nothing without removing the error. Preferably, the code should not refer to any headers that are not found on a regular Linux installation. If it must, you need to identify where they're obtainable from — yes, I can probably find GNU Radio if I have to, but I shouldn't need to do so.

Upvotes: 2

Related Questions