Rating@Mail.ru

Форум по операционной системе GNU/Linux и свободному программному обеспечению


Текущее время: 16 дек 2017, 21:45

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 7 ] 
Автор Сообщение
 Заголовок сообщения: вызов C++ кода из C
Непрочитанное сообщениеДобавлено: 10 мар 2017, 14:42 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 10265
Откуда: Харьков
Конкретная задача:
- код достаточно обстоятельной задачи, из области компьютерного зрения
- используется OpenCV
- в OpenCV есть API C & API C++ ... но API C++ намного богаче, а задача достаточно сложная...
- но и это не главное, в задаче очень много динамических объектов непредсказуемой размерности ... хотелось бы использовать STL
- вызывать хотелось бы из C-кода, 1 (2,3,...) достаточно простых итоговых вызова ... boolean признак "да/нет" на предмет распознавания некоторого образа
- и поместить этот C-код в DLL библиотеку для использования её в бэк-энде какого-то там WEB проекта.

Здесь вопрос связывания, линковки, приведение в соответствие соглашений вызовов C/C++ и заталкивание всего этого (и C++ и C) в shared DLL.

Задача чисто техническая...


Вернуться к началу
 Профиль Отправить личное сообщение  
 
 Заголовок сообщения: Re: вызов C++ кода из C
Непрочитанное сообщениеДобавлено: 10 мар 2017, 21:01 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 10265
Откуда: Харьков
Olej писал(а):
Задача чисто техническая...

Схема такая:

1. Код С++ в библиотеке DLL (файл child.cc):
Код:
#include "common.h"

int debug_level = 2;

bool predicat( test_t *t ) {
   return t->level == debug_level;
}

__attribute__ ((destructor)) static void on_exit( void ) {
   cout << "завершение: подчистка перед выгрузкой" << endl;
}


2. Общий файл определений (common.h) который делает объекты DLL доступными вызывающим программам (вот как-раз с ним то и пришлось повозиться ;-) ):
Код:
#ifndef CHILD_H
#define CHILD_H

#include <stdlib.h>

extern int debug_level;

typedef struct  {       // class test
   char s[ 77 ];
   int level;
} test_t;

#ifdef __cplusplus
#include <iostream>
using namespace std;
extern "C" {
#else
#include <stdbool.h>
#include <stdio.h>
#endif

bool predicat( test_t* );

#ifdef __cplusplus
}
#endif

#endif                  // CHILD_H


3. вызывающий (DLL) процесс на языке C (файл predicat.c):
Код:
#include "common.h"

static void on_exit( void ) {
   printf( "завершение процесса\n" );
}

int main( int argc, char *argv[] ) {
   atexit( on_exit );
   test_t t = { "", 2 };
   printf( "результат: %s\n", predicat( &t ) ? "TRUE" : "FALSE" );
   debug_level = 3;
   printf( "результат: %s\n", predicat( &t ) ? "TRUE" : "FALSE" );
   return 0;
}


4. вызывающий (ту же DLL) процесс, но теперь уже на языке C++ (файл predicat.cc):
Код:
#include "common.h"

static void on_exit( void ) {
   printf( "завершение процесса\n" );
}

int main( int argc, char *argv[] ) {
   atexit( on_exit );
   test_t t = { "", 2 };
   cout << "результат: " << ( predicat( &t ) ? "TRUE" : "FALSE" ) << endl;
   debug_level = 3;
   cout << "результат: " << ( predicat( &t ) ? "TRUE" : "FALSE" ) << endl;
}


Вернуться к началу
 Профиль Отправить личное сообщение  
 
 Заголовок сообщения: Re: вызов C++ кода из C
Непрочитанное сообщениеДобавлено: 10 мар 2017, 21:09 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 10265
Откуда: Харьков
Olej писал(а):
Схема такая:

Теперь собираем всё это вместе, Makefile :
Код:
TARGET = proxi
CHILD = child
TARGETM = $(TARGET)m
TARGETA = $(TARGET)a
TARGETP = $(TARGET)p

LIB = lib$(TARGET).so

CC  += -Wall -std=c99 -O3
CXX += -Wall -std=c++11 -O3

all: $(LIB) $(TARGETM) $(TARGETA) $(TARGETP)

$(LIB): $(CHILD).cc common.h
        $(CXX) -c -fpic -fPIC -shared $(CHILD).cc -o $(CHILD).o
        $(CXX) -shared -o $(LIB) $(CHILD).o
        rm -f *.o

$(TARGETM): $(TARGET).c $(CHILD).cc common.h
        $(CXX) -c $(CHILD).cc -o $(CHILD).o
        $(CC) -c $(TARGET).c -o $(TARGET).o
        $(CC) $(TARGET).o $(CHILD).o -lstdc++ -o $@
        rm -f *.o

$(TARGETA): $(TARGET).c common.h
        $(CC) $< -Bdynamic -L./ -l$(TARGET) -o $@

$(TARGETP): $(TARGET).cc common.h
        $(CXX) $< -Bdynamic -L./ -l$(TARGET) -o $@

clean:
        rm -f *.o $(LIB) $(TARGETM) $(TARGETA) $(TARGETP)

Собирается библиотека + 3 приложения:
Код:
[olej@dell libcpp]$ make
g++ -Wall -std=c++11 -O3 -c child.cc -o child.o
cc -Wall -std=c99 -O3 -c proxi.c -o proxi.o
cc -Wall -std=c99 -O3 proxi.o child.o -lstdc++ -o proxim
rm -f *.o
cc -Wall -std=c99 -O3 proxi.c -Bdynamic -L./ -lproxi -o proxia
g++ -Wall -std=c++11 -O3 proxi.cc -Bdynamic -L./ -lproxi -o proxip

Код:
[olej@dell libcpp]$ ls *proxi*
libproxi.so  proxia  proxi.c  proxi.cc  proxim  proxip

proxim - монолитная сборка C & C++ кодов в единое приложение, без всяких библиотек (для контроля);
proxia - приложение на чистом C, использующем библиотеку DLL libproxi.so на C++, которая, в свою очередь, использует libstdc++.so;
proxip - приложение на C++, использующее ту же библиотеку libproxi.so;


Вернуться к началу
 Профиль Отправить личное сообщение  
 
 Заголовок сообщения: Re: вызов C++ кода из C
Непрочитанное сообщениеДобавлено: 10 мар 2017, 21:13 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 10265
Откуда: Харьков
Olej писал(а):
proxim - монолитная сборка C & C++ кодов в единое приложение, без всяких библиотек (для контроля);
proxia - приложение на чистом C, использующем библиотеку DLL libproxi.so на C++, которая, в свою очередь, использует libstdc++.so;
proxip - приложение на C++, использующее ту же библиотеку libproxi.so;

Код:
[olej@dell libcpp]$ ./proxim
результат: TRUE
результат: FALSE
завершение процесса
завершение: подчистка перед выгрузкой

А для использования (проверки) DLL обязательно:
Код:
[olej@dell libcpp]$ export LD_LIBRARY_PATH=.

Или так:
Код:
[olej@dell libcpp]$ export LD_LIBRARY_PATH=`pwd`

А теперь используем DLL:
Код:
[olej@dell libcpp]$ ./proxia
результат: TRUE
результат: FALSE
завершение процесса
завершение: подчистка перед выгрузкой

[olej@dell libcpp]$ ./proxip
результат: TRUE
результат: FALSE
завершение процесса
завершение: подчистка перед выгрузкой


Вернуться к началу
 Профиль Отправить личное сообщение  
 
 Заголовок сообщения: Re: вызов C++ кода из C
Непрочитанное сообщениеДобавлено: 10 мар 2017, 21:23 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 10265
Откуда: Харьков
Olej писал(а):
А теперь используем DLL:

Внешнее имя (для link) функций а). образуется по правилам C, б). не содержит, как в C++, в имени типов параметров и возвращаемого значенияи в). может связываться как с кодом C, так и с кодом C++:
Код:
[olej@dell libcpp]$ nm libproxi.so | grep ' T '
0000000000000a20 T _fini
0000000000000820 T _init
0000000000000a10 T predicat

Проверен как вызов функций из библиотеки (predicat()), так и доступ (по записи!) к полям данных (debug_level) в библиотеке.
Код:
[olej@dell libcpp]$ nm libproxi.so | grep ' D '
0000000000201048 D debug_level
000000000020104c D _edata


Это проделывалось (мной) для систематизации, как подготовительная часть крупного порученного мне проекта ... но, может, как сведенное в систему, окажется и ещё кому полезным?


Вернуться к началу
 Профиль Отправить личное сообщение  
 
 Заголовок сообщения: Re: вызов C++ кода из C
Непрочитанное сообщениеДобавлено: 11 мар 2017, 00:43 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 10265
Откуда: Харьков
Olej писал(а):
Это проделывалось (мной) для систематизации, как подготовительная часть крупного порученного мне проекта

Т.е. подобная структура может применяться в самых разнообразных проектах:
- основной проект на C, построенный на API POSIX ...
- и узкий интерфейс (2, 3, 4... вызова) к обрабатывающей части...
- а сама обрабатывающая часть выполнена как DLL и написана на C++, но, самое главное, может использовать API обширных сторонних библиотек C++: STL, контейнеры, обощённые алгоритмы, компьютерное зрение OpenCV, регулярные выражения и т.д. и т.п.
- и даже там, где объектно-структурированные данные C++ (такие как контейнеры, или форматированные изображения) нужно передавать-возвращать между вызовами DLL, они в C-шной части (координирующей, вызывающей) просто преобразовываются к не типизированным указателям void* (так как это делается, например, при создании pthread_t).


Вернуться к началу
 Профиль Отправить личное сообщение  
 
 Заголовок сообщения: Re: вызов C++ кода из C
Непрочитанное сообщениеДобавлено: 03 май 2017, 10:06 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 10265
Откуда: Харьков
Olej писал(а):
Это проделывалось (мной) для систематизации, как подготовительная часть крупного порученного мне проекта ... но, может, как сведенное в систему, окажется и ещё кому полезным?

Во-первых, обнаружил, что не прикрепил к обсуждению готовый программный код, который обсуждается... :cry:
А это не в моих правилах.
Поэтому восполняю. ;-)

А, во-вторых, для чего и кому это может быть особенно интересно?
Для фронтэнд WEB-проектов, когда основная (т.е. вызываемая) часть этого фронтэнда написана на Go, скажем (или на Python), и нужен интерфейс к какой-то развитой библиотеке, использующей C++ - та же библиотека компьютерного зрения OpenCV, как характерный пример.
Написать из Go/Python интерфейс к коду C - не проблема, а вот к специфике C++ - довольно хлопотное дело.
И вот тут на помощь может прийти такое вот связывание.


Вложения:
libcpp.tgz [2.65 КБ]
Скачиваний: 22
Вернуться к началу
 Профиль Отправить личное сообщение  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 7 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB
[ Time : 0.231s | 19 Queries | GZIP : On ]