2

我一直面临这个警告。

我有一个创建多个线程的主 C++ 程序。这些线程运行特定类中的函数。为了做到这一点,这个类有一个静态函数,它返回我用来在这些线程中运行的真实函数。我将粘贴我的代码的相关部分,以便您更好地理解它。

这些是 Car.h 的相关部分,其函数在线程中运行的类的头文件:

[...]
class Car {

public:
    [...]
    void *GoForward(void);                 //Runs in the thread
    static void* GoForward_helper(void *); //Sends the previous one to the thread
    [...]

这是 Car.cpp 中作为参数传递给 pthread_create 的函数,它返回真正在线程中运行的函数。这是我发现在线程中运行不同类的函数的唯一方法:

[...]
void *Car::GoForward_helper(void *context) {

    //Just getting parameters, not big deal
    ThreadParameters* parameters = (ThreadParameters*) context;
    int newSlot = parameters->GetSlot();
    parameters->GetCar()->setSlot(newSlot);

    //Returns the function I want to run in the thread
    return parameters->GetCar()->GoForward();
}
[...]
void* Car::GoForward(void) {
    //Tasks which actually run in the thread
}
[...]

这些是发送到辅助函数的参数。没有什么相关的,为了您的方便,我粘贴它们:

[...]
class ThreadParameters {
public:
    ThreadParameters(Car*, int);
    Car* GetCar();
    int GetSlot();
    [...]
private:
    Car* context;
    int slot;
[...]

...最后这是 main() 中创建线程的代码:

[...]
vector<Car *> cars;    //Pointers to objects whose functions I want to run in threads
int threadsLaunched = 0;
pthread_t threads[numberOfThreads]; 
vector<int> freeSlots; //The number of threads is limited
[...]          
int slot = freeSlots.at(0);
threadCode = pthread_create(&threads[slot], NULL, 
                    &Car::GoForward_helper, 
                    new ThreadParameters(cars.at(threadsLaunched), slot));

我正在使用 Oracle Solaris Studio 12.3 在 Solaris 10 中对其进行编程。在构建项目时,我收到与 main() 中创建线程的行相对应的警告:

“main.cpp”,第 80 行:警告(不合时宜):在调用 pthread_create(unsigned*, const _pthread_attr*, extern "C" void*( )时类型为 extern "C" void*( )(void ) 的形式参数 3 (void ), void*) 正在传递 void*( )(void )。

代码就像一个魅力,但我在编译时仍然收到这个警告,老实说,我讨厌没有一个完全干净的编译过程。我找到了几十个使用 extern "C" 的解决方案,但是这些解决方案都不符合我的代码结构,所以它们都不适合我,我想摆脱任何警告(解决它们,而不是隐藏它们)。

4

1 回答 1

7

您收到警告是因为pthread_create()需要一个指向函数 with 的指针C language linkage,但您传递Car::GoForward_helper的是具有C++ language linkage. 虽然在实践中这很可能会奏效,但这两者实际上是不同的;例如,C 和 C++ 链接函数可能使用不同的调用约定。

不幸的是,类成员(甚至是静态成员)不能具有 C++ 以外的语言链接。换句话说,严格按照规则的字母,不可能将静态成员函数用作预期 C 函数的回调。

为了解决这个问题,你必须让助手成为一个自由函数并给它 C 语言链接:

[...]
class Car {

public:
    [...]
    void *GoForward(void);                 //Runs in the thread
    [...]
};

extern "C" void* GoForward_helper(void *); //Sends GoForward() to the thread

像这样实现:

extern "C" void *GoForward_helper(void *context) {

    //Just getting parameters, not big deal
    ThreadParameters* parameters = (ThreadParameters*) context;
    int newSlot = parameters->GetSlot();
    parameters->GetCar()->setSlot(newSlot);

    //Returns the function I want to run in the thread
    return parameters->GetCar()->GoForward();
}

一个额外的选项,特别是如果函数需要类似成员的访问,您可以保留静态的并简单地委托给它:

[...]
class Car {

public:
    [...]
    void *GoForward(void);                 //Runs in the thread
    static void* GoForward_helper(void *); //Sends the previous one to the thread
    [...]
};

extern "C" void* GoForward_helper_C(void *);

像这样实现:

extern "C" void* GoForward_helper_C(void *arg) {
  return Car::GoForward_helper(arg);
}
于 2013-10-17T09:57:47.143 回答