Russian Qt Forum
Ноябрь 27, 2024, 06:21 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3 4   Вниз
  Печать  
Автор Тема: C headers (mixed C/C++)  (Прочитано 22771 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Январь 23, 2013, 18:51 »

Добрый день

Есть довольно обширное API/SDK на чистом С (без плюсов). Вот пример структуры данных из h файла
Код
C++ (Qt)
typedef struct {
float r, g, b;
} RGB_Float;
 
Этот тип входит в массу др структур которые я должен принимать и/или заполнять. Писать всякий раз так
Код
C++ (Qt)
c2.r = c0.r + c1.r;
c2.g = c0.g + c1.g;
c2.b = c0.b + c1.b;
 
весьма неудобно - хочется работать с комфортом. Конечно написать операторы + и др не вопрос, но как быть с хедером который без плюсов? Сам хедер править не запрещено, но надо учитывать

- SDK может периодически обновляться
- возможны небольшие проекты/утилитки на чистом С

Как бы Вы поступили?
Спасибо
Записан
Nagdiel
Гость
« Ответ #1 : Январь 23, 2013, 19:42 »

Можно написать модуль-обертку, основанную на оригинальном хедере и реализующую нужные операции, а затем в модулях, реализующих логику приложения, использовать эту обертку. При изменении в оригинальном API нужно будет скорректировать только модуль-обертку.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Январь 24, 2013, 06:33 »

Можно написать модуль-обертку, основанную на оригинальном хедере и реализующую нужные операции, а затем в модулях, реализующих логику приложения, использовать эту обертку. При изменении в оригинальном API нужно будет скорректировать только модуль-обертку.
Пример (псевдокод)
Код
C++ (Qt)
void DoSomething( some_c_struct * data )
{
...
data->colorOut = (data->color1 + data->color2) / 2;   // операторы для RGB_float
...
}
 
Прошу показать (схематично, в псевдокоде) как должен выглядеть модуль-обертка
Записан
kramer
Гость
« Ответ #3 : Январь 24, 2013, 07:53 »

Не совсем понятна суть вопроса. Что мешает определить операторы в отдельном хедере и использовать его в C++ части, не трогая оригинальный хедер?

MyCppHeader.h
Код
C++ (Qt)
#include <TheirAPIHeader.h>
 
inline const RGB_Float operator+(const RGB_Float& a, const RGB_Float& b) {
         RGB_Float result = {a.r+b.r, a.g+b.g, a.b+b.b};
         return result;
}
 
Записан
Nagdiel
Гость
« Ответ #4 : Январь 24, 2013, 09:10 »

Код:
[quote author=Igors link=topic=24026.msg170464#msg170464 date=1358998401]
Прошу показать (схематично, в псевдокоде) как должен выглядеть модуль-обертка
[/quote]

Да вот именно так, как kramer показал.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Январь 24, 2013, 15:08 »

Согласен, операторы можно взять со стороны, никаких минусов у такого решения не вижу. Но все же плюсового класса нет - и это ощутимо. Напр
Код
C++ (Qt)
// хотелось бы
struct RGB_Real {
RGB_Real( void ) { r = g = b = 0.0f; }
 
float Min( void ) const;
float Max( void ) const;
float Gray( void ) const;
// и.т.д
};
 
Конечно можно то же самое можно сделать в виде С ф-ций, но это как-то режет глаз, особенно при очень интенсивном использовании этой базовой струтуры
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #6 : Январь 24, 2013, 15:12 »

Код
C++ (Qt)
class RGB_Real : public RGB_Float
{
public:
   RGB_Real( void ) { r = g = b = 0.0f; }
 
   float Min( void ) const;
   float Max( void ) const;
   float Gray( void ) const;
};
 
« Последнее редактирование: Январь 24, 2013, 15:19 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Январь 24, 2013, 15:19 »

Код
C++ (Qt)
class RGB_Real : public RGB_Float
 
Этот путь я уже пробовал в одном проекте Улыбающийся В принципе - вполне удовлетворительно, но возникают множественные приведения (обычно по ссылке) - ведь во всех структурах SDK вмонтированы RGB_Float (а не RGB_Real)
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #8 : Январь 24, 2013, 15:22 »

но возникают множественные приведения (обычно по ссылке) - ведь во всех структурах SDK вмонтированы RGB_Float (а не RGB_Real)

Можно определить оператор приведения типа. Я пытался в одном примере все объединить, но так не понятно:
Код
C++ (Qt)
class RGB_Real
{
public:
 
   operator RGB_Float();
};
 

А по хорошему, нужно все перевести на классы (сделать полную прослойку) и использовать в пользовательском коде только их.
« Последнее редактирование: Январь 24, 2013, 15:24 от Old » Записан
kramer
Гость
« Ответ #9 : Январь 24, 2013, 15:30 »

Хмм, тогда можно сконструировать класс-обертку:
Код
C++ (Qt)
class MyRGB {
   MyRGB() { _rgb.r = _rgb.g = _rgb.b = 0.0f; }
   MyRGB(const RGB_Float& rgb) : _rgb(rgb) {}
   ~MyRGB() {}
 
    RGB_Float operator RGB_Float() { return reinterpret_cast<RGB_Float&>(*this); }
private:
   RGB_Float _rgb;
}
 
или даже без копирования
Код
C++ (Qt)
class MyRGB {
public:
   MyRGB() { _rgb.r = _rgb.g = _rgb.b = 0.0f; }
   MyRGB(RGB_Float& rgb) { this = reinterpret_cast<MyRGB*>&rgb; }
   ~MyRGB() {}
 
    RGB_Float& operator RGB_Float&() { return reinterpret_cast<RGB_Float&>(*this); }
    const RGB_Float& operator RGB_Float&() const { return reinterpret_cast<const RGB_Float&>(*this); }
private:
   RGB_Float _rgb;
}
 
но это, на мой взгляд, все-таки bad practice и вообще чревато. Хотя, если осторожно, то мне кажется, все-таки можно. Улыбающийся
« Последнее редактирование: Январь 24, 2013, 15:37 от kramer » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Январь 24, 2013, 15:36 »

А по хорошему, нужно все перевести на классы (сделать полную прослойку) и использовать в пользовательском коде только их.
Вот об этом я и хотел поговорить  Улыбающийся Латки ставить и сам умею - а вот как по-умному?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #11 : Январь 24, 2013, 15:41 »

Вот об этом я и хотел поговорить  Улыбающийся Латки ставить и сам умею - а вот как по-умному?
А что бы это обсудить, нужно видеть С API.
Как правило, прямая переделка всех структур в классы, удобства не прибавляет. Нужно абстрагироваться от Сишного кода и попытаться придумать удобный Плюсовый API, и под него адаптировать классы, в которых и прятать Сишные функции.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Январь 24, 2013, 16:22 »

А что бы это обсудить, нужно видеть С API.
Выложить его не могу, да и что там собственно видеть? typedef struct - вот и все, просто много

Как правило, прямая переделка всех структур в классы, удобства не прибавляет.
Это был первый (резвый) вариант, уже довольно давно. Достаточно редкое обновление базового SDK можно пережить  Главный минус - когда мне нужно отдать проект с исходниками - я должен мучительно переключить все хедеры, и ничего не могу использовать из написанного.

Нужно абстрагироваться от Сишного кода и попытаться придумать удобный Плюсовый API, и под него адаптировать классы, в которых и прятать Сишные функции.
В смысле вызовов ф-ций SDK - этот подход прекрасный. Но вот со структурами данных..
Записан
vregess
Гость
« Ответ #13 : Январь 24, 2013, 16:34 »

Все зависит от того, чего хочется получить.
Если нужно прозрачно работать с SDK, забыв, что это обертка, то делаем наследование, как уже писали

Код
C++ (Qt)
extern "C"
{
#include "rgb_float.h"
}
 
class Wrapper: public RGB_Float
{
public:
 Wrapper(const RGB_Float &);
 ...
}
 
делаем операторы присваивания и тд.

но возникают множественные приведения (обычно по ссылке) - ведь во всех структурах SDK вмонтированы RGB_Float (а не RGB_Real)

Чем это не устраивает?

Вариант 2. Делаем работу с оберткой более явной при помощи агрегирования, вместо наследования
Код
C++ (Qt)
class Wrapper:
{
public:
 Wrapper(const RGB_Float &);
 ...
 RGB_Float& data() {}
 const RGB_Float& data() const {}
 ...
private:
 RGB_Float m_val;
}
 
также добавляем всякие операторы для удобства работы Wrapper + RGB_Float (но не наоборот). Для связи с SDK используем Wrapper::data().
Я бы использовал вариант2 или что-то подобное, но то я.
В общем не совсем ясно, в чем конкретно сложность.

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Январь 24, 2013, 17:00 »

Чем это не устраивает?
..
В общем не совсем ясно, в чем конкретно сложность.
Не то чтобы "не устраивает" а "как лучше". Ну вот
Код
C++ (Qt)
//  void RaiseContract(RGB_Real &);  // здесь плюсовый класс для расчетоы
..
RaiseContract(c_struct->color);   // а данные в структуре С
..
 
В варианте с наследованием я так просто/естественно написать не могу, придется так
Код
C++ (Qt)
RaiseContract((RGB_Real &) c_struct->color);  
 
А Ваш вариант с агрегированием еще неудобнее
Код
C++ (Qt)
Wrapper temp(c_struct->color)
RaiseContract(temp);
c_struct->color =  temp.data();
 
Записан
Страниц: [1] 2 3 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.381 секунд. Запросов: 22.