簡體   English   中英

在C ++抽象類中將回調(用於C庫)實現為純虛擬的

[英]Implementing callback (for C library) as pure virtual in C++ abstract class

我在使用C音頻庫時遇到了一個問題(使用ASIO SDK構建的PortAudio,但這與該問題並沒有真正的關系;技術細節只會阻止我提出這個問題)

簡而言之,該庫中的某個C函數要求我給它提供一個回調函數,該回調函數返回某個值並接受某些參數。 為了清楚起見,假設回調應如下所示:

int callback(int arg)

對庫函數的調用如下所示:

theCLibraryFuntion(foo, bar, callback);

像這樣使用庫(即以過程C風格的方式)可以很好地工作,但是我想將與我相關的庫功能包裝在結構良好的C ++類中。 我需要的庫項目是迄今為止我最大的工作,因此面向對象設計對我來說是必須的。 我想在C ++中創建一個抽象類,為派生類提供一個純虛函數以實現,然后讓知道該庫的類將該實現用於回調。 換句話說,我需要實際的多態性,而不是討厭的函數指針。

到目前為止,我還無法編寫此類。 編譯器不允許我將任何類的非靜態成員函數作為回調傳遞給C庫函數。 我知道為什么,但是我想知道一些解決方法。 只要存在該變通辦法,只要它能夠為前端類提供多態行為,我就不在乎后端代碼變得多么邪惡。 如果不存在這樣的解決方法,那就去吧。 我非常了解C在后台的工作方式,但是我對C ++的OO功能的技術知識知之甚少,所以我將假設有一種方法。

提前致謝!

注意:一種可能會增加大量開銷的解決方法對我來說可能毫無價值。 我被迫使用此C portaudio庫,因為它是唯一使我的項目所需的音頻流延遲極短的API,因此,大幅增加開銷並不是真正的選擇。

您的代碼過於簡化。 在現實世界中,“庫函數”和回調都將具有void* “用戶數據”參數。 您可以將指向類實例的指針傳遞到“庫函數”的“用戶數據”中,並將其轉發到回調中,您可以在其中使用該指針訪問對象。

class CallbackImplBase {
public:
   virtual void CallbackImpl() = 0;
   static void CallbackToPass( void* userData )
   {
       static_cast<CallbackImplBase*>(userData)->CallbackImpl();           
   }
};

class ActualCallbackImpl : public CallbackImplBase {
     void CallbackImpl() { //implemented here }
};

ActualCallbackImpl callback;
callLibraryFunction( params,
   &CallbackImplBase::CallbackToPass, static_cast<CallbackImplBase*>( &callback ) );

請注意“ library function”調用的最后一個參數附近的static_cast 除非您具有多個繼承,否則您將不需要它,但無論如何它仍然存在。

據我所知,PortAudio中的回調(例如this )采用void*參數將用戶數據傳遞給它們。 通過將類指針作為用戶數據傳遞,並編寫一個小的靜態或非成員函數以注冊為與C兼容的回調,可以使用它來調用成員函數。 例如:

// C library function
typedef void (*c_library_callback)(void * user_data);
void c_library_start_stuff(c_library_callback, void * user_data);

// C++ class using it
class audio_thing {
public:
    virtual ~audio_thing() {} // Better have one of these in an abstract class

    void start_stuff() {
        c_library_start_stuff(&audio_thing::static_callback, this);
    }
private:
    // C-compatible callback forwards to the implementation
    static void static_callback(void * thing) {
        static_cast<audio_thing*>(thing)->callback();
    }

    // Derived classes implement the callback behaviour
    virtual void callback() = 0;
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM