2016-08-10 6 views
0

Я написал класс оболочки C++ для API C.forward объявить C typedef в заголовке C++

В моем классе-оболочке есть отдельный экземпляр-элемент структуры typedef, используемый в исходном API. Я не хочу изменять заголовочный файл API, но я также хочу скрыть все следы исходного API, поэтому НЕ хочу включать исходный заголовочный файл API в заголовок класса оболочки.

Я, вероятно, с видом на что-то действительно простое, но я не нахожу его. PIMPL - это вариант, но я бы предпочел искать альтернативы перед реорганизацией всей базы кода для одной мелочи.

wrapper.hpp

class myWrapper 
{ 
public: 
    myWrapper(); 

private: 
    originalTypedef *original; // forward declaration needed for originalTypedef 
}; 

wrapper.cpp

#include "wrapper.hpp" 
#include "originalAPI.h" 

myWrapper::myWrapper() 
{ 
    original = originalAPI_get(); 
} 

main.cpp

#include "wrapper.hpp" 

int main() 
{ 
    myWrapper wrapper = new myWrapper(); 
} 
+2

Можете ли вы предоставить нам [MCVE], пожалуйста? –

+0

Помимо того, что я предоставил? То, что я предоставил, более последовательное. – audiFanatic

+0

[PIMPL.] (Http://stackoverflow.com/questions/60570/why-should-the-pimpl-idiom-be-used) – user4581301

ответ

3

Параметры, которые я был в состоянии думать быстро:

  1. Вы можете повторить только typedef из C API в myWrapper.h.

    typedef struct the_original_struct_type originalTypedef; 
    
  2. Вы можете использовать void* в качестве переменной-члена в myWrapper и reinterpret_cast к originalTypedef* перед вызовом C API.

    class myWrapper 
    { 
        private: 
         void* original; 
    }; 
    
+0

Написал этот ответ, но это было первым. Следует помнить, что опция (1) применима только в том случае, если в будущем API C не изменится (так как вам придется обновлять обертку). Также вам может потребоваться использовать условный макрос «IS_ORIGINAL_C_API_INCLUDED» или такой, чтобы предотвратить множественные ошибки определения в myWrapper.cpp. –

+0

# 2 будет работать, но вы потеряете всю информацию о типе, так что будьте осторожны с кастингом. – JBRWilkinson

0

Что вы ищете что-то вроде рисунка Pimpl - вы обеспечиваете ++ API C и реализация затемненный от клиента:

Header File

// forward declare obfuscated implementation 
// we can do this because we're only using a ptr 
class Implementation; 

class Wrapper 
{ 
    public: 
     Wrapper(); 
     ~Wrapper(); 
     void doSomething(); 

    private: 
     Implementation * pImpl; 
    }; 

.cpp file

#include "originalAPI.h" 
    class Implementation 
    { 
    public: 
     void doSomething() 
     { 
     OriginalAPI_DoSomething(); 
     } 
    }; 

    Wrapper::Wrapper() 
    { 
    this->pImpl = new Implementation(); 
    } 

    Wrapper::~Wrapper() 
    { 
     delete pImpl; 
    } 

    void Wrapper::doSomething() 
    { 
     pImpl->doSomething; 
    } 
+0

Я ценю ответ, но я ищу альтернативу PIMPL. Кодовая база уже существует, и для этого требуется массивный рефакторинг для одной крошечной вещи – audiFanatic

+0

в порядке, поэтому просто вперед объявите originalTypeDef как его точный тип, но не определяйте его в заголовке. Таким образом, вам не нужно включать исходный заголовок api в заголовок обертки. – JBRWilkinson

1

Экзотическим решением было бы написать генератор кода, который читает в original_c_api.h, и выводит файл original_c_api_types.h, который включает только определения, типы и т. Д., Но не содержит никаких функций, а файл original_c_api_functions.h содержит объявления функций , Затем wrapper.h включает original_c_api_types.h и wrapper.cpp включает wrapper.h и original_c_api_functions.h. Генератор кода должен быть запущен как цель в вашем файле makefile.

Конечно, если у вас есть полномочия на изменение исходных файлов C api, это самое простое решение.