LINUX.ORG.RU

C и использование C++ библиотек


0

0

Возникла необходимость использования ++ библиотеки в С программе. Как уже понятно, в том и другом не слишком-то силен. Как это можно сделать (можно пример с кодом и ключиками компилятора?) и что rtfm'ить дабы понять от и до? Используется GCC, среда - UNIX, требования к коду по-видимому POSIX.

Заранее 10х!

anonymous

Никак:(

Точнее, если тебе доступны исходники ++ библиотеки, то можешь:

1. Убедиться, что нет глобальных/статич. переменных с нетривиальными конструкторами.
Если есть - увы:(

2. написАть враппер к необходимым вызовам на ЦеПП с прототипами, обернутыми
в extern "C".

3. Скомпилить эти врапперы в шареную либу, не забыв ключики fPIC, если на интеле.
Если на последнем этапе не сглючит GCC (а оно может!), то линкуйся на здоровье...

Die-Hard ★★★★★
()

Скорее всяк и поразному..

Если есть исходники - всё хорошо,
если последних нету, много wrapper-ов писать придётся.
Вот что пришло в голову сразу:
acppfunc.cxx:
=======================================
#include <iostream>

extern "C" void acppfunc(void);


//extern "C" void test::pinvect(void);

void acppfunc(void)
{
        std::cout << "c++ function called!\n";
}

class test
{
        int _isInstantiated;
public:
        test(){_isInstantiated=1;}

        static void pinvect(void){cout<<"jo jo jo ...santa is your daddy"<<endl;}

        static void* createNSet()
        {
                test *t=new test();
                return t;
        }

        static void useIt(void *op)
        {
                test *pt = (test*)op;
                pt->a_regular_member();
        }

        void a_regular_member(){cout<<"je je je ..fuckin' santa rules again: "<<_isInstantiated<<endl;}
};

typedef void (*cmfunc)(void*);
cmfunc hFunc=test::useIt;

typedef void* (*cofunc)(void);
cofunc iFunc=test::createNSet;

typedef void (*afunc)(void);
afunc gFunc=test::pinvect;
======================================

main.c:
======================================
#include <stdio.h>

extern void acppfunc(void);
typedef void (*afunc)(void);
extern afunc gFunc;

typedef void* (*cofunc)(void);
extern cofunc iFunc;
typedef void (*cmfunc)(void*);
extern cmfunc hFunc;

main()
{
        void *op;
        printf("calling a c++ function from c\n");
        acppfunc();
        gFunc();


        op = iFunc();
        hFunc(op);
        printf("done\n");
}
==================================================
Makefile:
==================================================
main: acppfunc.o main.o
        g++ main.o acppfunc.o -o main

main.o: main.c
        gcc -c main.c -o main.o

acppfunc.o: acppfunc.cxx
        g++ -c acppfunc.cxx -o acppfunc.o

clean:
        rm -f *.o main
==================================================
При выполнении ./main увидим, что:
=============================================
calling a c++ function from c
c++ function called!
jo jo jo ...santa is your daddy
je je je ..fuckin' santa rules again: 1
done
===========================================

anonymous
()

P.S. ну и собственно убивать объект потом не забываем, но это я думаю понятно как.

anonymous
()

Исходники есть. Если говорить более конкретно, то речь идет о Gigabase - http://www.garret.ru/~knizhnik/gigabase/

Степень нетривиальноси конструкторов оценить в принципе не могу потому как с Ц++ практически не знаком. Пишу на pure C, но реально опыта еще очень мало. Учусь по докам-книжкам. Нельзя ли поподробнее насчет extern, ну и вообще этих дел - встраивают ведь и ассемблерный код, и т.п. Т.е. хочется понять, как это должно делаться, какие грабли можно огрести, а так же где примерно про это читать. Да, насчет -fPIC тоже можно поподробнее - уже несколько раз видел референсы по этому поводу, и понял, что грабли достаточно распространенные.

anonymous
()
Ответ на: Скорее всяк и поразному.. от anonymous

2anonymous (*) (2002-08-29 22:27:28.398):
Ух ты!
Сильно сказано:
#######################################
main: acppfunc.o main.o
        g++ main.o acppfunc.o -o main

main.o: main.c
        gcc -c main.c -o main.o
########################################
А насколько оно работает? Я имею в виду, есть ли какая-нибудь 
"официяльная" гарантия, что линковка с помощью g++ main функции,
скомпиленной gcc, обеспечит нужные ЦеПП инициализации, скажем,
глобальных переменных с виртуальными методами?

А как насчет других ЦеПП компилеров?

И, BTW, полученная программа все же будет не Це, а ЦеПП по своей 
природе.

Die-Hard ★★★★★
()
Ответ на: комментарий от anonymous

Про шареные либы (насчет fPIC и shared опций) например:
http://www.tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

В теории, отсутствие опции fPIC не должно быть фатальным, но просто приводить
к многократному присутствию в памяти разделяемого кода. На практике без
fPIC  заработаешь сегфолт - как я понял, из-за багов в libc6.

Мне ни  разу не удалось помирить Си с ЦеПП - хотя я не очень-то и старался.
Люди пишут, что этого сделать нельзя - ну, я и поверил после нескольких 
неудачных попыток...

> встраивают ведь и ассемблерный код...
Встроить Си в ЦеПП прогу - ни малейших проблем, равно, как и ассемблер.
А вот наоборот...

Насчет extern -

Декларация

extern "C" ...
или

extern "C" 
{
...
...
}
говорит ЦеПП компилеру, чтобы он не искажал имена функций, типа, они Сишные.

Поэтому во всех стандартных хедерах видим нечто типа
#ifdef __cplusplus
extern "C"
{
#endif

...

#ifdef __cplusplus
}
#endif

IMHO хорошая книжина:
http://www.icce.rug.nl/documents/cplusplus/

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Эххх, Die-Hard, официальных гарантий никаких нет..

с гцц у меня всегда работала а использоваля такого рода хрени неоднократно.
С ицц, тоже чего-то один раз делал и там помнится поизвращавшись тоже заставил пахать

Работает усё обычно на ура даже в сложных связках.

Насчет того что в конечном итоге это будет cpp a ne c:
ну типа да, наверно, g++ же делано.
Но я исхожу из стандартной задачи:
есть куча С кода и из него нужно делать хитрые callback-и в С++


anonymous
()

ОК, спасибо за примеры и разъяснения!
Буду читать и тыркаться ;=)

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.