Russian Qt Forum

Программирование => С/C++ => Тема начата: Igors от Январь 23, 2013, 18:51



Название: C headers (mixed C/C++)
Отправлено: Igors от Январь 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 может периодически обновляться
- возможны небольшие проекты/утилитки на чистом С

Как бы Вы поступили?
Спасибо


Название: Re: C headers (mixed C/C++)
Отправлено: Nagdiel от Январь 23, 2013, 19:42
Можно написать модуль-обертку, основанную на оригинальном хедере и реализующую нужные операции, а затем в модулях, реализующих логику приложения, использовать эту обертку. При изменении в оригинальном API нужно будет скорректировать только модуль-обертку.


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 24, 2013, 06:33
Можно написать модуль-обертку, основанную на оригинальном хедере и реализующую нужные операции, а затем в модулях, реализующих логику приложения, использовать эту обертку. При изменении в оригинальном API нужно будет скорректировать только модуль-обертку.
Пример (псевдокод)
Код
C++ (Qt)
void DoSomething( some_c_struct * data )
{
...
data->colorOut = (data->color1 + data->color2) / 2;   // операторы для RGB_float
...
}
 
Прошу показать (схематично, в псевдокоде) как должен выглядеть модуль-обертка


Название: Re: C headers (mixed C/C++)
Отправлено: kramer от Январь 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;
}
 


Название: Re: C headers (mixed C/C++)
Отправлено: Nagdiel от Январь 24, 2013, 09:10
Код:
[quote author=Igors link=topic=24026.msg170464#msg170464 date=1358998401]
Прошу показать (схематично, в псевдокоде) как должен выглядеть модуль-обертка
[/quote]

Да вот именно так, как kramer показал.


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 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;
// и.т.д
};
 
Конечно можно то же самое можно сделать в виде С ф-ций, но это как-то режет глаз, особенно при очень интенсивном использовании этой базовой струтуры


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 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;
};
 


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 24, 2013, 15:19
Код
C++ (Qt)
class RGB_Real : public RGB_Float
 
Этот путь я уже пробовал в одном проекте :) В принципе - вполне удовлетворительно, но возникают множественные приведения (обычно по ссылке) - ведь во всех структурах SDK вмонтированы RGB_Float (а не RGB_Real)


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 24, 2013, 15:22
но возникают множественные приведения (обычно по ссылке) - ведь во всех структурах SDK вмонтированы RGB_Float (а не RGB_Real)

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

А по хорошему, нужно все перевести на классы (сделать полную прослойку) и использовать в пользовательском коде только их.


Название: Re: C headers (mixed C/C++)
Отправлено: kramer от Январь 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 и вообще чревато. Хотя, если осторожно, то мне кажется, все-таки можно. :)


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 24, 2013, 15:36
А по хорошему, нужно все перевести на классы (сделать полную прослойку) и использовать в пользовательском коде только их.
Вот об этом я и хотел поговорить  :) Латки ставить и сам умею - а вот как по-умному?


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 24, 2013, 15:41
Вот об этом я и хотел поговорить  :) Латки ставить и сам умею - а вот как по-умному?
А что бы это обсудить, нужно видеть С API.
Как правило, прямая переделка всех структур в классы, удобства не прибавляет. Нужно абстрагироваться от Сишного кода и попытаться придумать удобный Плюсовый API, и под него адаптировать классы, в которых и прятать Сишные функции.


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 24, 2013, 16:22
А что бы это обсудить, нужно видеть С API.
Выложить его не могу, да и что там собственно видеть? typedef struct - вот и все, просто много

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

Нужно абстрагироваться от Сишного кода и попытаться придумать удобный Плюсовый API, и под него адаптировать классы, в которых и прятать Сишные функции.
В смысле вызовов ф-ций SDK - этот подход прекрасный. Но вот со структурами данных..


Название: Re: C headers (mixed C/C++)
Отправлено: vregess от Январь 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 или что-то подобное, но то я.
В общем не совсем ясно, в чем конкретно сложность.



Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 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();
 


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 24, 2013, 17:06
Выложить его не могу, да и что там собственно видеть? typedef struct - вот и все, просто много
Да выкладывать не обязательно. Это нужно что бы определиться какие классы нужны и как они будут взаимодействовать.

В смысле вызовов ф-ций SDK - этот подход прекрасный. Но вот со структурами данных..
А что со структурами данных? Часть из них может вообще исчезнуть для конечного пользователя, другая адаптироваться для объектного API.


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 24, 2013, 17:08
Код
C++ (Qt)
class RGB_Real
{
public:
   RGB_Real( const RGB_Float & );
};
 
//  void RaiseContract(RGB_Real &);  // здесь плюсовый класс для расчетоы
..
RaiseContract(c_struct->color);   // а данные в структуре С
..
 

А лучше, что бы данных в C-структурах больше не было.


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 24, 2013, 17:38
Код
C++ (Qt)
class RGB_Real
{
public:
   RGB_Real( const RGB_Float & );
};
 
//  void RaiseContract(RGB_Real &);  // здесь плюсовый класс для расчетоы
..
RaiseContract(c_struct->color);   // а данные в структуре С
..
 
А так c_struct->color не модифицируется (не говоря уже о том что копирование из одной структуры в др не украшает)

Это нужно что бы определиться какие классы нужны и как они будут взаимодействовать.
..
А что со структурами данных? Часть из них может вообще исчезнуть для конечного пользователя, другая адаптироваться для объектного API.
Если С структура большая - с ней проблем не возникает, прекрасно работает все что предлагалось выше. И унаследоваться хорошо, и хранить член-указатель на исходную С структуру. Неприятности (мелкие но много) с простейшими классами ("цвет", "точка" и.т.п.) потому что в рабочем коде к ним масса обращений


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 24, 2013, 17:45
А так c_struct->color не модифицируется (не говоря уже о том что копирование из одной структуры в др не украшает)

Вот по этому:
А лучше, что бы данных в C-структурах больше не было.

В пользовательском коде уже не должно быть C-структур, весь пользовательский код должен работать с врапперами.


Название: Re: C headers (mixed C/C++)
Отправлено: vregess от Январь 24, 2013, 18:34
А что если хранить в обертке указатель/ссылку?
Код
C++ (Qt)
class Wrapper
{
public:
 Wrapper(RGB_Float &data): m_data(data) {}
 
private:
 RGB_Float &m_data;
}
...
 
RaiseContract(Wrapper(c_struct->color));
 

тогда все манипуляции будут отражаться на исходном объекте


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 24, 2013, 18:55
Вот по этому:
А лучше, что бы данных в C-структурах больше не было.
В пользовательском коде уже не должно быть C-структур, весь пользовательский код должен работать с врапперами.
Хотелось бы, но пока не вижу как это аккуратно сделать

А что если хранить в обертке указатель/ссылку?
Код
C++ (Qt)
class Wrapper
{
public:
 Wrapper(RGB_Float &data): m_data(data) {}
 
private:
 RGB_Float &m_data;
}
...
 
RaiseContract(Wrapper(c_struct->color));
 

тогда все манипуляции будут отражаться на исходном объекте
Получается что структура ну как бы "слишком мала" чтобы ее врапить. Вот с большими структурами это гуд. А так напр нужен массив RGB_Float - и не объявлять же массив Wrapper'ов. И опять RGB_Float проникает, и опять его придется приводить


Название: Re: C headers (mixed C/C++)
Отправлено: m_ax от Январь 24, 2013, 19:05
А что если хранить в обертке указатель/ссылку?
Код
C++ (Qt)
class Wrapper
{
public:
 Wrapper(RGB_Float &data): m_data(data) {}
 
private:
 RGB_Float &m_data;
}
...
 
RaiseContract(Wrapper(c_struct->color));
 

тогда все манипуляции будут отражаться на исходном объекте

Баян)
Тогда уж так:
Код
C++ (Qt)
class Wrapper : public std::reference_wrapper<RGB_Float> {};
 


Но у такого варианта всё равно есть свой минус..

Можно сделать лучше, пожалуй) 


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 24, 2013, 19:22
Тогда уж так:
Код
C++ (Qt)
class Wrapper : public std::reference_wrapper<RGB_Float> {};
 

Но у такого варианта всё равно есть свой минус..
Ох уж это пьянствование std..  :'( Лучше самописного может на копейку, а здесь так вообще ничем. Зато как затрудняет нормальному человеку понимание текста - не задачей занимаемся, а так, "эрудицию" развиваем.


Название: Re: C headers (mixed C/C++)
Отправлено: m_ax от Январь 24, 2013, 19:30
Тогда уж так:
Код
C++ (Qt)
class Wrapper : public std::reference_wrapper<RGB_Float> {};
 

Но у такого варианта всё равно есть свой минус..
Ох уж это пьянствование std..  :'( Лучше самописного может на копейку, а здесь так вообще ничем. Зато как затрудняет нормальному человеку понимание текста - не задачей занимаемся, а так, "эрудицию" развиваем.

Точно) Зачем использовать готовые стандартные решения, когда всегда приятнее потратить лишнее время для написания своего велосипеда)


Название: Re: C headers (mixed C/C++)
Отправлено: Пантер от Январь 24, 2013, 19:49
Igors, не соглашусь с тобой. STL вариант сразу дает понять, что хотел программист. А в самописных решенияъ нужно разобраться, чтобы понять.


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 24, 2013, 20:14
Точно) Зачем использовать готовые стандартные решения, когда всегда приятнее потратить лишнее время для написания своего велосипеда)
А не уйдет ли вся силенка в запоминание стандартных решений? Это ох как часто бывает.

Однако вернемся к теме. От того что оно стандартное - легче почему-то не стало :)  Минусы точно такие же как и в варианте ck


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 24, 2013, 20:25
А не уйдет ли вся силенка в запоминание стандартных решений? Это ох как часто бывает.
Еще чаще бывает полное переписывание чужих велосипедов на стандартные решения, для облегчения дальнейшего сопровождения системы.

Однако вернемся к теме. От того что оно стандартное - легче почему-то не стало :)  Минусы точно такие же как и в варианте ck
У любого костыля будут минусы.
Если делать основательно, то должно быть три слоя: пользовательский, враппер, С-библиотека, с обязательным условием - крайние слои ничего не знают друг про друга.


Название: Re: C headers (mixed C/C++)
Отправлено: m_ax от Январь 24, 2013, 20:42
А не уйдет ли вся силенка в запоминание стандартных решений? Это ох как часто бывает.

На запоминание стандартных решений может и уйдёт силёнка..
Но в любом случае, от этого больше пользы, чем вреда..

А чердачное хламокопание, с целью написать очередное решение.. хм.. Это не развитие (если вы об этом), а простаивание на месте( 


Название: Re: C headers (mixed C/C++)
Отправлено: m_ax от Январь 24, 2013, 23:58
Однако вернемся к теме. От того что оно стандартное - легче почему-то не стало :)  Минусы точно такие же как и в варианте ck

Вот, на мой взгляд, самое оптимальное решение для данной задачи:

Код
C++ (Qt)
template <class T>
class wrapper : public std::reference_wrapper<T>
{
public:
   wrapper(T &x) : std::reference_wrapper<T>(x) {}
 
   wrapper& operator=(const T &x) {
       this->get() = x;
       return *this;
   }
 
   wrapper& operator=(const wrapper<T> &x) {
       this->get() = x.get();
       return *this;
   }
 
// + Ещё какой либо функционал, в зависимости от задачи..
};
 
template <class T>
inline const T operator+(const wrapper<T> &x, const wrapper<T> &y) {
   return x.get() + y.get();
}
 
template <class T>
inline const T operator-(const wrapper<T> &x, const wrapper<T> &y) {
   return x.get() - y.get();
}
 
void print(int x) {
   std::cout << "print int: value = " << x << std::endl;
}
 
template <class T>
void print(wrapper<T> &w) {
   std::cout << "print wrapper: value = " << w << std::endl;
}
 
int main()
{
   int a = 10;
   int b = 20;
   int c = 0;
 
   wrapper<int> wa(a);
   wrapper<int> wb(b);
   wrapper<int> wc(c);
 
   wc = wa + wb;
 
   print(wc);
 
   print(c);
 
   return 0;
}
 

А теперь,  заменяем int на RGB_Float и пишем в отдельном хедере необходимые для него (RGB_Float) операторы (+,- и т.д.)
делаем typedef:
Код
C++ (Qt)
typedef wrapper<RGB_Float> RGB_Real;
 
 
и радуемся жизни)


Название: Re: C headers (mixed C/C++)
Отправлено: twp от Январь 25, 2013, 00:12
Если используется Qt то можно задействовать QSharedData в купе с QSharedDataPointer (или даже QExplicitlySharedDataPointer, если надо поведение ссылок).


Название: Re: C headers (mixed C/C++)
Отправлено: vregess от Январь 25, 2013, 08:39
Баян)
Тогда уж так:
Код
C++ (Qt)
class Wrapper : public std::reference_wrapper<RGB_Float> {};
 


Хорошее замечание)

Вот, на мой взгляд, самое оптимальное решение для данной задачи:

Это врядли, тк вариант с оберткой тс не особо устраивает. Так что более лучшая обертка получается не самым оптимальным решением:

Получается что структура ну как бы "слишком мала" чтобы ее врапить. Вот с большими структурами это гуд. А так напр нужен массив RGB_Float - и не объявлять же массив Wrapper'ов.
Тут я в принципе согласен.


Конечно написать операторы + и др не вопрос, но как быть с хедером который без плюсов? Сам хедер править не запрещено, но надо учитывать
Что имелось ввиду под "как быть с хедером"? И зачем его править? Делаем header.hpp, в который включаем header.c и вспомогательные функции.
Может и не надо создавать дополнительных классов, а все перенести в статические функции (или сейчас так и сделано)?


Название: Re: C headers (mixed C/C++)
Отправлено: m_ax от Январь 25, 2013, 09:07
Это врядли, тк вариант с оберткой тс не особо устраивает. Так что более лучшая обертка получается не самым оптимальным решением:

Честно говоря, я уже не припомню, когда нашего ТС, что-либо полностью устраивало, особенно в плане stl  :)

А так, да..
Вообще, я согласен с подходом Old-а, но на это и писанины уйдёт порядочно..
Но решать, конечно, igors-у..
 


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 25, 2013, 09:58
Вот, на мой взгляд, самое оптимальное решение для данной задачи:
В упоении показать Вашу (неуклонно растущую) технику Вы не обратили внимания что это за класс, хотя об этом уже был разговор выше. Вы механически применяете стандартное решение для классов-сущностей, а оно здесь совсем не к месту.
Код
C++ (Qt)
void DrawBuffer( RGB_Float * buf, int width, int height );
 
Да, размер буфера может быть сотни мегабайт (12 байт на пыксель). Какой здесь нафиг враппер?

У любого костыля будут минусы.
Если делать основательно, то должно быть три слоя: пользовательский, враппер, С-библиотека, с обязательным условием - крайние слои ничего не знают друг про друга.
Ну так показываем (схематично) как это должно выглядеть. Зачем нам костыль, давайте основательно. Только вот дальше слов и охаивания велосипедистов дело почему-то не идет  :)


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 25, 2013, 10:08
Ну так показываем (схематично) как это должно выглядеть. Зачем нам костыль, давайте основательно. Только вот дальше слов и охаивания велосипедистов дело почему-то не идет  :)
Так а что показывать? API С-библиотеки не доступно, обсуждаем одну структуру RGB_Float.

Для пользователя она должна быть скрыта за классом RGBReal и все доступные методы должны использовать ее:
Код
C++ (Qt)
void DrawBuffer( const std::vector<RGBReal> &buf, int width, int height );
 

Для хранения буферов можно сделать свой контейнер:
Код
C++ (Qt)
class PixBuffer
{
public:
   RGBReal &at( int x, int y );
   const RGBReal &at( int x, int y ) const;
}
 
void DrawBuffer( const PixBuffer &buf, int width, int height );
 

Здесь нужно садиться и смотреть какие сущности нужны для пользовательского кода и как сделать их удобное взаимодействие, и за этими классами прятать весь C API. И не в коем случае не наоборот!


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 25, 2013, 10:47
Так а что показывать? API С-библиотеки не доступно, обсуждаем одну структуру RGB_Float.
Ну "больше входной информации/подробностей" не всегда гарантирует более плодотворное обсуждение  :) Простой вызов с массивом просто показывает что враппер зднсь не подходит. А вот более живой пример
Код
C++ (Qt)
typedef struct {
RGB_Float * mBufferBase;  // данные буфера (3 float на точку)
 
// здесь десяток членов - простых типов
SInt32 mFrame;
        ...
 
C_Rect mBufferRect;            // SDK структура - самописный rectangle
C_Matrix mMatrix;  // SDK структура - самописная матрица 4х4
 
// здесь опять десяток простых
double mTime;
        ...
 
} DrawBufferRec, * DrawBufferPtr;
 
Ну и я получаю такой вызов
Код
C++ (Qt)
SInt32 DrawBuffer( DrawBufferPtr theBuffer );   // мой код должен быть в этом вызове API
 
Что посоветуете?


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 25, 2013, 11:10
Что посоветуете?

Нужно сесть и продумать, а как было бы удобно это использовать в клиентском коде.
Например, решаем использовать три сущности:
Код
C++ (Qt)
// Рендер - может генерировать DrawBuffer
class Renderer
{
public:
   DrawBuffer run( ... );    // В run используется C-API, возвращает же она уже C++ объект.
};
 
// Рисовальщик - умеет его выводить на всякие разности
class Drawer
{
public:
   void draw( const DrawBuffer &buf );
};
 
// Буфер - сам буфер
class DrawBuffer
{
public:
   DrawBuffer( int w, int h );
 
private:
   DrawBuffer( DrawBufferPtr );    // Прячем конструктор, который умеет создавать объект из C-структуры
   friend class Renderer;                  // Даем возможность методу Renderer::run использовать спрятанный конструктор для создания объектов из C-структуры
}
 

Для пользователя нет C-API, все спрятано в этих трех классах.


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 25, 2013, 13:39
Код
C++ (Qt)
// Буфер - сам буфер
class DrawBuffer
{
   ...
   DrawBuffer( DrawBufferPtr );    // Прячем конструктор, который умеет создавать объект из C-структуры
   ...
}
 
Для пользователя нет C-API, все спрятано в этих трех классах.
Прошу показать как будет выглядеть плюсовый DrawBuffer и как он должен конструироваться из исходной С-шной структуры DrawBufferRec.


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 25, 2013, 14:08
Как вариант, он будет хранить указатель на C-структуру DrawBuffer
Код
C++ (Qt)
DrawBuffer::DrawBuffer( DrawBufferPtr ptr ) :
   m_drawBuffer( ptr )
{
}
 
DrawBuffer::DrawBuffer( int w, int h ) :
   m_drawBuffer( new DrawBufferRec )
{
   m_drawBuffer->width = w;
   m_drawBuffer->height = h;
}
 

А можно разложить поля С-структуры в поля класса:
Код
C++ (Qt)
class DrawBuffer
{
   PixArray m_bufferBase;    // Предполагается, что конструктор PixArray умеет конструироваться из указателя на буфер RGB_Float
public:
   DrawBuffer( DrawBufferPtr ptr ) :
       m_bufferBase( ptr->mbufferBase )
   {
   }
}
 


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 26, 2013, 06:51
Как вариант, он будет хранить указатель на C-структуру DrawBuffer
Из этого неясно как полностью избавиться от обращений к С-структурам. Ладно, я расскажу как я понял, а Вы поправьте что надо. Итак:

- для каждой С структуры создаем С++ класс используя наследование или агрегацию (по вкусу)
- если структура содержит др  С структуры, то в плюсовый класс добавляем методы возвращающие ссылку на ++ класс

Пример
Код
C++ (Qt)
class DrawBuffer_cpp : public DrawBufferRec {
...
RGB_Float_cpp * BufferBase( void )  { return (RGB_Float_cpp *) mBufferBase; }
Rect_cpp & BufferRect( void )   { return (Rect_cpp &) mBufferRect; }
Matrix_cpp & Matrix( void );     { return (Matrix_cpp &) mMatrix; }
}
Этот путь самый капитальный (не "костыль"). Так или нет?


Название: Re: C headers (mixed C/C++)
Отправлено: m_ax от Январь 26, 2013, 09:15

Пример
Код
C++ (Qt)
class DrawBuffer_cpp : public DrawBufferRec {
...
RGB_Float_cpp * BufferBase( void )  { return (RGB_Float_cpp *) mBufferBase; }
Rect_cpp & BufferRect( void )   { return (Rect_cpp &) mBufferRect; }
Matrix_cpp & Matrix( void );     { return (Matrix_cpp &) mMatrix; }
}
Этот путь самый капитальный (не "костыль"). Так или нет?

Это тот же костыль.. при таком то публичном наследовании от сишной структуры..


Название: Re: C headers (mixed C/C++)
Отправлено: Bepec от Январь 26, 2013, 09:23
Сколько бы решений не предлагали, любое решение отличное от Си структуры кто-нибудь да будет называть костылём. С++ - костыль от С. Qt - костыль от C++.



Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 26, 2013, 09:42
Это тот же костыль.. при таком то публичном наследовании от сишной структуры..
Никто не мешает унаследоваться private. А вообще уверяю Вас что после первого, даже скромного, инженерного расчета Ваш энтузиазм к private и геттерам/сеттерам резко упадет, возможно до нуля  :)

Ладно, то к делу не относится. Так в чем же "костыльность" и как "по всем правилам"?   


Название: Re: C headers (mixed C/C++)
Отправлено: m_ax от Январь 26, 2013, 09:49
Это тот же костыль.. при таком то публичном наследовании от сишной структуры..
Никто не мешает унаследоваться private. А вообще уверяю Вас что после первого, даже скромного, инженерного расчета Ваш энтузиазм к private и геттерам/сеттерам резко упадет, возможно до нуля  :)

Ладно, то к делу не относится. Так в чем же "костыльность" и как "по всем правилам"?  

Как правильно уже написал Old.

Я бы ещё указал в классах (интерфейс cpp) дружественные функции (те новые плюсовые, которые предоставляются пользователю), чтобы в них можно было вызывать низкоуровневый сишный аналог и передавать в него приватный сишный член (агрегированный).. (ой, чота ржу :-X )

  


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 26, 2013, 09:57
Из этого неясно как полностью избавиться от обращений к С-структурам.
Весь пользовательский код будет работать с объектами DrawBuffer_cpp, а про DrawBufferRec будет знать только прослойка.

- для каждой С структуры создаем С++ класс используя наследование или агрегацию (по вкусу)
Я несколько раз писал, что по моему мнению так делать нельзя. Как правило получается не удобная фигня.
Нужно сесть и представить (с точки зрения пользовательского кода), а как бы мне было удобно эффективно это все описать на C++.
Для примера, есть библиотека для работы с БД. Решение в лоб, это описать классы Поле, Запись, Таблица, Соединение и потом из Полей формировать Записи, из Записей Таблицы и т.д. А мне оказалось удобней оставить только две сущности: Запрос и Соединение. В которые, я и спрятал все обращения С-функциям. Весь пользовательский код знает только про эти два класса и пользуется только их интерфейсом. Бэкенд БД легко меняется, хочешь SQLite, MySQL, ...

Всегда забаляли такие классы. Зачем городить класс, если предоставляешь полный доступ к его внутренностям.  ???
Пример
Код
C++ (Qt)
class DrawBuffer_cpp : public DrawBufferRec {
...
RGB_Float_cpp * BufferBase( void )  { return (RGB_Float_cpp *) mBufferBase; }
Rect_cpp & BufferRect( void )   { return (Rect_cpp &) mBufferRect; }
Matrix_cpp & Matrix( void );     { return (Matrix_cpp &) mMatrix; }
}


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 26, 2013, 09:58
Никто не мешает унаследоваться private. А вообще уверяю Вас что после первого, даже скромного, инженерного расчета Ваш энтузиазм к private и геттерам/сеттерам резко упадет, возможно до нуля  :)
Что такое инженерный расчет и какое отношение он имеет к классам?


Название: Re: C headers (mixed C/C++)
Отправлено: m_ax от Январь 26, 2013, 09:59
А вообще уверяю Вас что после первого, даже скромного, инженерного расчета Ваш энтузиазм к private и геттерам/сеттерам резко упадет, возможно до нуля  :)

Я занимаюсь расчётами..  достаточно серьёзными (производительность приоритетна). Никаких проблем с сетерами и гетерами не испытывал..  ;)


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 26, 2013, 10:19
Весь пользовательский код будет работать с объектами DrawBuffer_cpp, а про DrawBufferRec будет знать только прослойка.
Ну это понятно, но как в DrawBuffer_cpp должны быть представлены члены которые в DrawBufferRec были С-структурами (RGB_Float, C_Matrix, C_Rect)?

Я несколько раз писал, что по моему мнению так делать нельзя. Как правило получается не удобная фигня.
Нужно сесть и представить (с точки зрения пользовательского кода), а как бы мне было удобно эффективно это все описать на C++.
Я понимаю о чем Вы говорите, но в данном случае мне просто нужны ++ эквиваленты примитивных структур (RGB_Float, C_Matrix, C_Rect) - и ничего более 


Название: Re: C headers (mixed C/C++)
Отправлено: m_ax от Январь 26, 2013, 10:25
... но в данном случае мне просто нужны ++ эквиваленты примитивных структур (RGB_Float, C_Matrix, C_Rect) - и ничего более 
Я всё никак понять не могу, а какой в этом тогда смысл?



Название: Re: C headers (mixed C/C++)
Отправлено: m_ax от Январь 26, 2013, 11:09
... но в данном случае мне просто нужны ++ эквиваленты примитивных структур (RGB_Float, C_Matrix, C_Rect) - и ничего более 
Я всё никак понять не могу, а какой в этом тогда смысл?



Если только ради дополнительных функций..
1) написать все необходимые функции для сишных примитивов.. (в отдельном хедере)
2)


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 26, 2013, 11:21
Если только ради дополнительных функций..
1) написать все необходимые функции для сишных примитивов.. (в отдельном хедере)
Все-таки прочли тему :)  Конечно можно и так, минус что свои аналогичные плюсовые структуры есть (без них не проживешь), поэтому возникают многочисленные приведения.


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 26, 2013, 11:28
Я понимаю о чем Вы говорите, но в данном случае мне просто нужны ++ эквиваленты примитивных структур (RGB_Float, C_Matrix, C_Rect) - и ничего более 

Код
C++ (Qt)
extern "C"
{
typedef struct matrix matrix_type;
void matrix_rotate_x( matrix_type *m, real a );
void matrix_scale( matrix_type *m, real s );
}
 
class Matrix
{
public:
   void rotate_x( real a );
   void scale( real s );
 
private:
   matrix_type m_matrix;
 
// а лучше
// class priv;
// priv    *d;
};
 
// ---
 
void Matrix::rotate_x( real a )
{
   matrix_rotate_x( &m_matrix, a );
}
 
void Matrix::scale( real s )
{
   matrix_scale( &m_matrix, s );
}
 

С одной стороны (пользовательский код) виден только интерфейс Matrix, с другой стороны все реализуется через С-функции.


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 26, 2013, 11:30
Все-таки прочли тему :)  Конечно можно и так, минус что свои аналогичные плюсовые структуры есть (без них не проживешь), поэтому возникают многочисленные приведения.
Все приведения (если и будут) только в интерфейсном слое (Matrix).


Название: Re: C headers (mixed C/C++)
Отправлено: Igors от Январь 27, 2013, 12:39
Все приведения (если и будут) только в интерфейсном слое (Matrix).
Я согласен со всем что Вы говорите - но все-таки из Ваших слов не понимаю как же нужно делать  :) Получив вызов API я имею на входе большую С структуру - ну привел или создал ++ структуру, ясно. Но как же мне в этой ++ структуре иметь удобный доступ к ++ под-структурам (сpp_RGB_Float, cpp_Matrix, cpp_Rect)? Я предложил оформить аксессоры - нет. Тогда как?

Ладно, не буду больше настаивать, тема уже слишком велика, в принципе обсуждение было полезным. Спасибо


Название: Re: C headers (mixed C/C++)
Отправлено: Old от Январь 27, 2013, 22:42
Тогда как?
Возвращать такие объекты  (Point, Rect, Matrix) только по значению (с техникой implicitly shared это будет не накладно) или константной ссылке. И соответственно, нужны полноценные сеттеры.