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

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

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

Предполагаю надо сделать правильный makefile, т.е. правильные ключи у gcc, но не могу найти.
...
Рейтинг: 0 / 0
использование C++ и С в одном проекте
    #38145463
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
использование C++ и С в одном проекте
    #38145665
plr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
plr
Гость
Попробую такую конструкцию, спасибо.

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

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

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


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

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

И как мне лучше построить makefile? gcc и/или g++? Я читал, что g++ это тот же gcc, только с определенными параметрами. Библиотеку собираю g++, а wrapper чем собирать? А основной проект собираю gcc, в нем подключаются заголовочные файлы wrapper, будет ли он собираться gcc?
...
Рейтинг: 0 / 0
использование C++ и С в одном проекте
    #38147109
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
использование C++ и С в одном проекте
    #38147576
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
plrНаверно в отдельных от библиотеки cpp и h -файлах?


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

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

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

gcc и/или g++?

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

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

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


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

Им же.

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

Да

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

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

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


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


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


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

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

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

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


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