Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / использование C++ и С в одном проекте / 14 сообщений из 14, страница 1 из 1
11.02.2013, 00:32
    #38145413
plr
plr
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
использование C++ и С в одном проекте
Основной проект на С (linux), есть библиотека в исходниках на С++.

Основной проект собирается gcc, библиотека - g++.

Соответственно не пойму как мне подключить (начать использовать функции) библиотеки в основном проекте.

Предполагаю надо сделать правильный makefile, т.е. правильные ключи у gcc, но не могу найти.
...
Рейтинг: 0 / 0
11.02.2013, 04:48
    #38145463
Пётр Седов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
использование C++ и С в одном проекте
2 plr:
Попробуйте использовать «extern "C"», примерно так:
lib.cpp:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
extern "C" void lib_func() {
  try {
    // C++-код
    ...
  } catch (...) {
    // не выпускаем C++-исключения за пределы функции
  }
}

lib.h:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
#ifndef LIB_H
#define LIB_H

#ifdef __cplusplus
extern "C" {
#endif

void lib_func();

#ifdef __cplusplus
}
#endif

#endif // !LIB_H

main.c:
Код: plaintext
1.
2.
3.
4.
5.
6.
#include "lib.h"

int main() {
  lib_func();
  return 0;
}
...
Рейтинг: 0 / 0
11.02.2013, 11:24
    #38145665
plr
plr
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
использование C++ и С в одном проекте
Попробую такую конструкцию, спасибо.

А как бороться с проблемой компиляции основного проекта на Си, в котором подключаю заголовки из С++ отсутствие файлов библиотек, например, <list>, <cstddef>?
...
Рейтинг: 0 / 0
11.02.2013, 11:44
    #38145708
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
использование C++ и С в одном проекте
plrОсновной проект на С (linux), есть библиотека в исходниках на С++.

Основной проект собирается gcc, библиотека - g++.

Соответственно не пойму как мне подключить (начать использовать функции) библиотеки в основном проекте.


Если основной проект на С, собрать его с библиотекой на С++ не получится.
С++ код может использовать код С-библиотек, а наоборот -- С -код использовать С++ библиотеки -- невозможно.
Для того, чтобы С -код мог использовать С++ библиотеку, надо, чтобы в С++-ной библиотеке были бы интерфейсы (API) на чистом С. Это далеко не у всех библиотек есть.
Если такого API нет -- можно теоретически сделать самому маленькую обертку. C++ кода маленькой адаптирующей С-библиотекой.
Этот код должен быть написан на С++.
...
Рейтинг: 0 / 0
11.02.2013, 11:49
    #38145721
plr
plr
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
использование C++ и С в одном проекте
MasterZiv, спасибо за объяснение. Пример обертки где можно посмотреть? Или Пётр Седов как раз его привёл?
...
Рейтинг: 0 / 0
11.02.2013, 16:19
    #38146354
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
использование C++ и С в одном проекте
Да, Пётр привёл примерную реализацию врапера для одного метода из С++ной библиотеки.
...
Рейтинг: 0 / 0
11.02.2013, 20:04
    #38146781
plr
plr
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
использование C++ и С в одном проекте
Прошу еще подсказать мне как лучше реализовать wrapper.

Наверно в отдельных от библиотеки cpp и h -файлах?

И как мне лучше построить makefile? gcc и/или g++? Я читал, что g++ это тот же gcc, только с определенными параметрами. Библиотеку собираю g++, а wrapper чем собирать? А основной проект собираю gcc, в нем подключаются заголовочные файлы wrapper, будет ли он собираться gcc?
...
Рейтинг: 0 / 0
12.02.2013, 07:08
    #38147109
Пётр Седов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
использование C++ и С в одном проекте
2 plr:

plrПрошу еще подсказать мне как лучше реализовать wrapper.Например, у нас есть C++-библиотека, содержащая один класс Num_List:
num_list.h
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
#ifndef NUM_LIST_H
#define NUM_LIST_H

#include <list>

class Num_List {
  // неявное копирование запрещено
  Num_List(const Num_List& nl); // нет реализации
  Num_List& operator=(const Num_List& nl); // нет реализации
public:
  Num_List(int min, int max);
  void add(int elem);
  int get_count() const;
  int get_elem(int index) const;
private:
  int _min, _max;
  std::list<int> _elems;
};

inline int Num_List::get_count() const {
  return _elems.size();
}

#endif // !NUM_LIST_H

num_list.cpp
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
#include "num_list.h"
#include <stdexcept> // для invalid_argument
#include <iterator> // для advance

using namespace std;

Num_List::Num_List(int min, int max) {
  if (min <= max) /* всё хорошо */;
  else throw invalid_argument("Num_List::Num_List");

  _min = min;
  _max = max;
}

void Num_List::add(int elem) {
  if ((_min <= elem) && (elem <= _max)) /* всё хорошо */;
  else throw invalid_argument("Num_List::add");

  _elems.push_back(elem); // может бросить bad_alloc
}

int Num_List::get_elem(int index) const {
  if ((0 <= index) && (index < static_cast<int>(_elems.size()))) /* всё хорошо */;
  else throw invalid_argument("Num_List::get_elem");

  list<int>::const_iterator it = _elems.begin();
  advance(it, index);
  return *it;
}

Мы хотим, чтобы функциональность этого класса была доступна в C-коде. Для этого пишем функции-обёртки над каждым методом класса:
lib.h
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
#ifndef LIB_H
#define LIB_H

#include <limits.h> // для INT_MAX

typedef enum {
  _result_ok,
  _result_error_alloc_mem_failed,
  _result_error_invalid_param,
  _result_error_unknown,
  _result_force_int = INT_MAX // костыль, чтобы enum хранился как int
} Result_Code;

#ifdef __cplusplus
class Num_List;
#else
typedef struct { int dummy; } Num_List;
#endif

#ifdef __cplusplus
extern "C" {
#endif

Result_Code num_list_new(int min, int max, Num_List** list);
Result_Code num_list_delete(Num_List* list);
Result_Code num_list_add(Num_List* list, int elem);
Result_Code num_list_get_count(const Num_List* list, int* count);
Result_Code num_list_get_elem(const Num_List* list, int index, int* elem);

#ifdef __cplusplus
}
#endif

#endif // !LIB_H

wrappers.cpp
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
#include "lib.h"
#include "num_list.h"
#include <new> // для bad_alloc
#include <stdexcept> // для invalid_argument

// !!! можно вызывать только в рамках catch
static Result_Code result_code_from_exception() {
  try {
    // повторно возбуждаем то же самое исключение
    throw;
  }
  catch (std::bad_alloc& e) { return _result_error_alloc_mem_failed; }
  catch (std::invalid_argument& e) { return _result_error_invalid_param; }
  catch (...) { return _result_error_unknown; }
}

extern "C" Result_Code num_list_new(int min, int max, Num_List** list) {
  try {
    *list = new Num_List(min, max);
  } catch (...) {
    return result_code_from_exception();
  }
  return _result_ok;
}

extern "C" Result_Code num_list_delete(Num_List* list) {
  delete list;
  return _result_ok;
}

extern "C" Result_Code num_list_add(Num_List* list, int elem) {
  try {
    list->add(elem);
  } catch (...) {
    return result_code_from_exception();
  }
  return _result_ok;
}

extern "C" Result_Code num_list_get_count(const Num_List* list, int* count) {
  try {
    *count = list->get_count();
  } catch (...) {
    return result_code_from_exception();
  }
  return _result_ok;
}

extern "C" Result_Code num_list_get_elem(const Num_List* list, int index, int* elem) {
  try {
    *elem = list->get_elem(index);
  } catch (...) {
    return result_code_from_exception();
  }
  return _result_ok;
}

При этом C++-исключения переводятся в коды возврата, потому что компилятор C не обязан знать про C++-исключения.
Пример использования (на чистом C):
main.c
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
#include "lib.h"
#include <stdio.h>

void demo() {
  Result_Code rc;
  Num_List* list = NULL;
  int count, i, elem;

  rc = num_list_new(/*min:*/0, /*max:*/100, &list);
  if (rc != _result_ok) goto cleanup;

  rc = num_list_add(list, 50);
  rc = num_list_add(list, 100);
  rc = num_list_add(list, 500);

  rc = num_list_get_count(list, &count);
  if (rc != _result_ok) goto cleanup;
  printf("%i element(s):\n", count);
  for (i = 0; i < count; i++) {
    rc = num_list_get_elem(list, i, &elem);
    if (rc != _result_ok) goto cleanup;
    printf("  %i\n", elem);
  }

cleanup:
  if (list != NULL) {
    rc = num_list_delete(list);
  }
}

int main() {
  demo();
  return 0;
}

вывод на консоль
Код: plaintext
1.
2.
2 element(s):
  50
  100

plrНаверно в отдельных от библиотеки cpp и h -файлах?Я разместил функции-обёртки в отдельном файле (wrappers.cpp), чтобы не захламлять код библиотеки.

plrИ как мне лучше построить makefile? gcc и/или g++?Я на создание makefile-ов не заморачиваюсь. Я компилирую проект в Code::Blocks. Там у каждого файла есть свойства, одно из которых -- «compiler variable». Если оно установлено в «CPP» (по умолчанию), то файл компилируется как C++-код, а если в «CC» -- то как C-код.

plrБиблиотеку собираю g++, а wrapper чем собирать?Функции-обёртки написаны на C++, поэтому файл wrappers.cpp надо компилировать как C++-код.

plrА основной проект собираю gcc, в нем подключаются заголовочные файлы wrapper, будет ли он собираться gcc?Заголовочный файл lib.h, содержащий упоминания всех функций-обёрток, специально сделан так, что его можно спокойно #include-ать в C-шные исходники.
...
Рейтинг: 0 / 0
12.02.2013, 13:02
    #38147576
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
использование C++ и С в одном проекте
plrНаверно в отдельных от библиотеки cpp и h -файлах?


ДА, в отдельных лучше. Если библиотека не твоя.
Если твоя, то можно и в тех же, зависит от библиотеки и многих прочих факторов.

И как мне лучше построить makefile?

Эт твоё дело...

gcc и/или g++?

Для компиляции библиотеки и врапера нужно использовать g++.

Я читал, что g++ это тот же gcc, только с определенными параметрами.

нет. Пока на твойм уровне понимания думай, что С компилируется GCC, С++ -- G++.


Библиотеку собираю g++, а wrapper чем собирать?

Им же.

А основной проект собираю gcc,

Да

в нем подключаются заголовочные файлы wrapper, будет ли он собираться gcc?

Да, будет.
...
Рейтинг: 0 / 0
15.02.2013, 14:26
    #38152865
использование C++ и С в одном проекте
Пётр СедовМы хотим, чтобы функциональность этого класса была доступна в C-коде. Для этого пишем функции-обёртки над каждым методом класса
А если мне нужен класс посложнее, например, универсальный контейнер boost::multi_index, где все на шаблонах сделанно? Как к нему писать функции-обертки, чтобы универсальность не потерялась и можно было любые типы/индексы использовать?
...
Рейтинг: 0 / 0
15.02.2013, 16:05
    #38153072
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
использование C++ и С в одном проекте
функции-обёрткиПётр СедовМы хотим, чтобы функциональность этого класса была доступна в C-коде. Для этого пишем функции-обёртки над каждым методом класса

А если мне нужен класс посложнее, например, универсальный контейнер boost::multi_index,


То пишешь C-API посложнее.


функции-обёрткигде все на шаблонах сделанно?


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

функции-обёрткиКак к нему писать функции-обертки, чтобы универсальность не потерялась и можно было любые типы/индексы использовать?

Универсальность поретяется. С не имеет поддержки generic programming, и соответственно его там никак не использовать.
...
Рейтинг: 0 / 0
16.02.2013, 00:00
    #38153680
multi_index
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
использование C++ и С в одном проекте
MasterZivС не имеет поддержки generic programming, и соответственно его там никак не использовать.
И что там используют тогда вместо boost::multi_index? Каждый раз наколенке с нуля пишут?
...
Рейтинг: 0 / 0
17.02.2013, 22:42
    #38154935
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
использование C++ и С в одном проекте
multi_index,

Разное, каждый свое.
Есть универсальные библиотеки, есть частные. Нередко пишутся свои библиотеки.
Что такое multi index не знаю, никогда не использовал.
...
Рейтинг: 0 / 0
17.02.2013, 22:57
    #38154952
использование C++ и С в одном проекте
multi_indexMasterZivС не имеет поддержки generic programming, и соответственно его там никак не использовать.
И что там используют тогда вместо boost::multi_index? Каждый раз наколенке с нуля пишут?
Да. Не любят шаблоны - городят тонны кода или мучаются с громоздкими дефайнами.
А если попробовать переписать код с вариадиками на чистый С, то получится полная жесть.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / использование C++ и С в одном проекте / 14 сообщений из 14, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]