Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
 Аватар для tarakan.nvkz
1 / 1 / 0
Регистрация: 10.09.2011
Сообщений: 146

Программа с библиотеками калькулятора. Не могу собрать

04.04.2016, 10:48. Показов 2629. Ответов 38
Метки нет (Все метки)

Максимально подробно. Есть компьютер с win7 на котором виртуальная машина ubuntu. Пишу в codeblocks под win, собираю в ubuntu.
Задание было написать библиотеку реализующие функции калькулятора. На выходе библиотека, файл использующий ее, заголовочный файл.
исходный код библиотеки calc.c:
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int add(int i1, int i2)
{int a;
    a=i1+i2;
    return a;
}
 
int usb(int i1, int i2)
{ int a;
    a=i1-i2;
    return a;
}
 
int mul(int i1, int i2)
{ int a;
    a=i1*i2;
    return a;
}
 
int div(int i1, int i2)
{ int a;
    a=i1/i2;
    return a;
}

Файл main.c использующий библиотеку:
Кликните здесь для просмотра всего текста
C
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
#include <stdio.h>
#include "/media/sf_SHARE/Sborka/library/mylib.h"
void main()
{
char c;
int i1;
int i2;
int a;
printf("pervoe chislo ");
scanf("%d",&i1);
 
printf("vtoroe chislo ");
 scanf("%d",&i2);
 
 
while (1)
{
 puts(" 1 - add");
 puts(" 2 - usb");
 puts(" 3 - mul");
 puts(" 4 - div");
 puts(" 0 - exit");
 c=getchar();
 switch(c)
 {case '1':a=add(i1,i2);
  break;
  case '2': a=usb(i1,i2);
  break;
  case '3': a=mul(i1,i2);
  break;
  case '4': a=div(i1,i2);
  break
  case '0': return 0;
  default : puts(" Error!");
 }
 printf("Rezultat=%d \n", a);
}
 
}

и заголовочный файл mylib.h:
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
#ifndef MYLIB_H_INCLUDED
#define MYLIB_H_INCLUDED
 
int add(int i1, int i2);
int usb(int i1, int i2);
int mul(int i1, int i2);
int div(int i1, int i2);
 
#endif // MYLIB_H_INCLUDED

Все это дело я закинул в общую папку между win и ubuntu.
В терминале ubuntu получил обьектный calc.o файл:
gcc -c calc.c
Далее создал статическую библиотеку libmy1.a из файла calc.o:
ar r libmy1.a *.o
Удалил обьектные файлы:
rm *.o
Хотел создать обьектный файл из main.c:
gcc -c main.c
Но увидел ошибку:
Кликните здесь для просмотра всего текста
main.c: In function ‘main’:
main.c:33:3: error: expected ‘;’ before ‘case’
case '0': return 0"

что я делаю не верно? прикладываю файлы.
Вложения
Тип файла: rar Sborka.rar (3.6 Кб, 2 просмотров)
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.04.2016, 10:48
Ответы с готовыми решениями:

Необходимо собрать проект со всеми библиотеками в одну папку, чтобы можно было его передавать на другие ПК.
Python 3.4, GUI wxPython. Необходимо собрать проект со всеми библиотеками в одну папку, чтобы можно было его передавать на другие ПК. Мне...

Не могу разобраться с библиотеками
Пишу первую программу &quot;mp3 плеер на C#&quot; (курсовая работа) и у меня возник ряд вопросов которые не решил прочтением информации в интернете. ...

VB6: не могу скомпилировать exe-файл со встроенными библиотеками
Здравствуйте. Я не могу скомпилировать exe-файл со встроенными библиотеками. Это вообще возможно? Ответьте кто-нибудь из умнейших.

38
128 / 126 / 60
Регистрация: 22.01.2014
Сообщений: 464
07.04.2016, 12:57
Я как понял одна функция - одна библиотека. Вам нужно использовать динамическую загрузку(dlopen,dlsym) библиотек и их функций. Для загрузки списка плагинов можно использовать opendir,readdir.

Для начала вам нужно разработать интерфейс функций калькулятора. Это набор импортируемых функций для каждого плагина.
Например:
C++
1
2
3
    const char getCalcFuncName(); //возвращает имя реализованной в плагине функции
    int getCalcFuncArgumentCount();//возвращает количество элементов функции плагина
    double calFunc(double a,...);//Сама функция плагина
И все плагины(в виде shared libs, ".so") должны придерживаться этой системы имен экспортируемых функции. Это и есть интерфейс плагина, в том смысле, каком я имел ввиду.
В клиентской программе будем загружать динамический и формировать список(лучше динамический массив) плагинов, и используя загруженные указатели на функции,можно их запускать для получения результата.
В этом ничего особо сложного нет, но просто много механической работы.
0
 Аватар для tarakan.nvkz
1 / 1 / 0
Регистрация: 10.09.2011
Сообщений: 146
07.04.2016, 14:01  [ТС]
nikolay1982, давайте попробуем по порядку? я не совсем понял как реализовать то что вы предложили, но это бесспорно именно то что требуется в задании.
1. Я создаю четыре файла, в каждом 1 функция (+,-,*,/).
2. Создаю 4 динамические библиотеки, с названиями функций (libadd.so и т.д.)
Как мне подключать их в свой файл main.c? какой должен быть заголовочный файл (или его вообще не должно быть)?
Допустим я с помощью
C
1
void *dlopen (const char *filename, int flag);
открываю библиотеку в указатель в void *library_1 (и так каждую?)
затем
C
1
void *dlsym(void *library_1, char *symbol);
загружаю нужную мне функцию (ну то есть одну единственную для каждой библиотеки).
а если библиотеки нет? то как она откроет только те которые смогла найти? я запутался окончательно.
0
128 / 126 / 60
Регистрация: 22.01.2014
Сообщений: 464
07.04.2016, 14:13
Вы можете контролировать загрузку dll, dlopen возвращает NULL, если не удалось загрузить библиотеку.
К кому же я предлагал использовать opendir,readdir для получения списка существующих плагинов(из папки plugins, как в задании).
Сделайте это сначала с одной библиотекой-плагином, если сможете сделать, то легко сделаете остальные три.
0
 Аватар для tarakan.nvkz
1 / 1 / 0
Регистрация: 10.09.2011
Сообщений: 146
07.04.2016, 14:27  [ТС]
nikolay1982, я загружу список библиотек из папки plagins, мне же нужно их куда присвоить, нужен массив указателей? и потом открывать каждый указатель функцией dlopen?
0
128 / 126 / 60
Регистрация: 22.01.2014
Сообщений: 464
07.04.2016, 14:42
Не обязательно. Да вам нужен массив, что в него вы будете записывать, это надо продумать структуру данных.
Можно по обходу файлов в директории сразу загружать нужные функции. При этом имена(пути файлов) вам нужны только временно.
0
 Аватар для tarakan.nvkz
1 / 1 / 0
Регистрация: 10.09.2011
Сообщений: 146
08.04.2016, 07:16  [ТС]
nikolay1982, смотрите
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
/* заголовочный файл для работы с динамическими библиотеками */
#include <dlfcn.h>
int main(int argc, char* argv[])
{
void *ext_library; // хандлер внешней библиотеки
int rezult=0;      // значение для теста
double (*func)(double x); // переменная для хранения адреса функции
ext_library = dlopen("../plagins/libadd.so",RTLD_LAZY); //загрузка библиотеки
if (!ext_library)
    {
        //если ошибка, то вывести ее на экран
        fprintf(stderr,"dlopen() error: %s\n", dlerror());
        return 1;
    };
    //загружаем из библиотеки требуемую процедуру
func = dlsym(ext_library, argv[1]);
 
    //закрываем библиотеку
    dlclose(ext_library);
}
а как теперь воспользоватся загруженной из библиотеки функцией?

Добавлено через 4 минуты
и я вообще правильно ее загружаю?
Bash
1
2
3
4
5
6
7
8
После этого можно работать с библиотекой. 
А работа эта заключается в получении адреса требуемой функции из библиотеки.
Получить адрес функции или переменной можно по ее имени с помощью функции:
 
void *dlsym(void *handle, char *symbol);
Для этой функции требуется адрес загруженной библиотеки handle,
 полученный при открытии функцией dlopen(). 
Требуемая функция или переменная задается своим именем в переменной symbol.
я не совсем понял что значит задается своим именем в переменной symbol..
0
128 / 126 / 60
Регистрация: 22.01.2014
Сообщений: 464
08.04.2016, 09:03
Лучший ответ Сообщение было отмечено tarakan.nvkz как решение

Решение

Первый раз я увидел не этот код, вы его правили что ли.
Цитата Сообщение от tarakan.nvkz Посмотреть сообщение
//закрываем библиотеку dlclose(ext_library);
Это нужно делать когда вам уже не нужны функции библиотеки, обычно это делается при выходе из приложения.
void *dlsym(void *handle, char *symbol); symbol - задает имя функции- помните, я говорит, что нужно задать интерфейс, то есть систему имен функций, которая будет одинаковой для всех плагинов.
В моем примере это double calFunc(double a,...); -> symbol="calFunc".
Но это определение с ... может показаться непонятным, поэтому более простое double calFunc(double a,double b);
Теперь как вызывать функцию. Стандартные правила для указателя на функцию.
C++
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
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
 
//#define TEST_INTER_FUNC_PTR 1
 
 double add_calFunc(double a,double b){
    return a+b;
}
 
int main(void)
{
    //обявляем переменную, которая является указателем на функцию
    double (*myPlugin1_calFunc)(double a,double b);
    double ret;
    #ifdef TEST_INTER_FUNC_PTR
    myPlugin1_calFunc=add_calFunc;
    #else
    void *ext_library; // хандлер внешней библиотеки
     //int rezult=0;      // значение для теста
    double (*func)(double x); // переменная для хранения адреса функции
    ext_library = dlopen("../plagins/libadd.so",RTLD_LAZY); //загрузка библиотеки
    //по заданию вроде "plugins" -u
    if (!ext_library)
    {
        //если ошибка, то вывести ее на экран
        fprintf(stderr,"dlopen() error: %s\n", dlerror());
        return 1;
    };
    myPlugin1_calFunc=(double (*)(double a,double b))dlsym(ext_library,"calcFunc");
    if (myPlugin1_calFunc==NULL){
        fprintf(stderr,"dlsym error: not found symbol\n" );
        dlclose(ext_library);
        return 1;
    }
    #endif
    
    ret=myPlugin1_calFunc(0.5,2.4);//вызываем функцию
    printf("answer:%f\n",ret);
    ret=(*myPlugin1_calFunc)(0.5,2.4);//вызываем функцию, можно и так
    printf("answer:%f\n",ret);
    #ifndef TEST_INTER_FUNC_PTR
    dlclose(ext_library);
    #endif
    return 0;
}
1
 Аватар для tarakan.nvkz
1 / 1 / 0
Регистрация: 10.09.2011
Сообщений: 146
08.04.2016, 13:13  [ТС]
nikolay1982, в вашем примере вы работаете с функцией
C
1
2
3
double add_calFunc(double a,double b){
    return a+b;
}
которая обьявлена в том же файле что и main? вы в этой функции проводите какие то операции, у вас в ней есть ретерн, вы указателю myPlugin1_calFun присваивате эту функцию. А зачем? если я буду загружать не add функцию, а любую другую, зачем мне в ней эта логика return a+b;? или это просто для теста?
Затем вы в этот же указатель загружаете функцию из библиотеки, причем в symbol пишите "calcFunc", которая больше нигде не используется, то есть непонятно зачем вообще нужно это имя функции. А если у меня будет 2 функции в библиотеке, как она узнает какую функцию поместить в myPlugin1_calFunc?
Простите что так много вопросов, я просто очень хочу разобраться, и вижу что вы компетентный человек, который к тому же не отказывает в помощи.

Добавлено через 21 минуту
Цитата Сообщение от tarakan.nvkz Посмотреть сообщение
Затем вы в этот же указатель загружаете функцию из библиотеки, причем в symbol пишите "calcFunc", которая больше нигде не используется, то есть непонятно зачем вообще нужно это имя функции. А если у меня будет 2 функции в библиотеке, как она узнает какую функцию поместить в myPlugin1_calFunc?
с этим разобрался, просто не понял о чем вы говорили, а код перечитал и понял. Это одинаковые имена в исходных кодах библиотек, чтобы можно было используя одно имя обращатся к функции из любой библиотеки, я прав?

Добавлено через 6 минут
nikolay1982, все действительно работает, теперь я наконец то понял как работает dlopen и dlsym!
Теперь нужно с помощью opendir и readdir по одному считать все названия файлов из папки plugins, из тех которые являются библиотеками считать функции и предложить пользователю для выбора, если я правильно понимаю.

Добавлено через 1 минуту
nikolay1982, не могли бы вы подсказать как правильно работать с opendir и readdir?

Добавлено через 2 часа 2 минуты
Цитата Сообщение от nikolay1982 Посмотреть сообщение
Можно по обходу файлов в директории сразу загружать нужные функции. При этом имена(пути файлов) вам нужны только временно.
я буду обходить директорию, а как считывать из библиотеки список ее функций? в dlsum сразу нужно указывать название, а если все таки реализовать не одну, а несколько функций в одной библиотеке?
0
128 / 126 / 60
Регистрация: 22.01.2014
Сообщений: 464
08.04.2016, 17:10
Вы много вопросов задали,возможно вы не поняли что я в код добавил внутреннюю проверку.
Если раскоментировать эту строку, то будет работать по другому.
Цитата Сообщение от nikolay1982 Посмотреть сообщение
//#define TEST_INTER_FUNC_PTR 1
Цитата Сообщение от nikolay1982 Посмотреть сообщение
#ifdef TEST_INTER_FUNC_PTR
myPlugin1_calFunc=add_calFunc;
#else
void *ext_library; // хандлер внешней библиотеки
Это все я для примера привел.

Добавлено через 4 минуты
Теперь простой пример с opendir,readdir:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <dirent.h>
 
int main()
{
    DIR *dir;
    struct dirent *entry;
 
    dir = opendir("/usr");
    while ((entry = readdir(dir)) != NULL) {
        printf("%s\n", entry->d_name);//здесь просто вывод имени файла, вам же нужна загрузка plugin-а
    }
    closedir(dir);
    return 0;
}
Вот вам простой пример обхода по содержимому каталога.
0
 Аватар для tarakan.nvkz
1 / 1 / 0
Регистрация: 10.09.2011
Сообщений: 146
09.04.2016, 00:33  [ТС]
nikolay1982, хорошо, а как выполнить загрузку функций, то есть если их имена не calcFunc, а другие, как их показать/считать их на выбор?
0
128 / 126 / 60
Регистрация: 22.01.2014
Сообщений: 464
09.04.2016, 08:00
создайте тип структуры в которой, будут хранится указатели на функции плагина.
Типа примерно:
C++
1
2
3
4
5
6
typedef struct _TPluginFunc{
    const char *name;
   double (*calcFunc)(double,double);//Можно для упрощения создать тип этой функции
  //далее следуют другие указатели на функции
  //... 
} TPluginFunc;
Потом вы можете объявить глобально массив TPluginFunc pluginFuncs[100], либо использовать malloc и т.д.
Сначала заполнить его нулями.
При обходе каталога с плагинами заполнить его загруженными функциями.
1
 Аватар для tarakan.nvkz
1 / 1 / 0
Регистрация: 10.09.2011
Сообщений: 146
09.04.2016, 10:48  [ТС]
nikolay1982, огромное спасибо, в понедельник попробую написать, может еще что нибудь спрошу) вы мне очень помогли(помогаете).
0
 Аватар для tarakan.nvkz
1 / 1 / 0
Регистрация: 10.09.2011
Сообщений: 146
11.04.2016, 14:23  [ТС]
nikolay1982, сейчас сделал в пока в таком виде:
Кликните здесь для просмотра всего текста
C
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
#include <stdio.h>
#include <stdlib.h>
/* заголовочный файл для работы с динамическими библиотеками */
#include <dlfcn.h>
/* заголовочный файл для работы с opendir */
#include <dirent.h>
 
int main(void)
{
    //Объявляем переменные
DIR *dir;
struct dirent *entry;
double i1,i2;
double (*myPlugin1_calFunc)(double a,double b);
void *ext_library; // хандлер внешней библиотеки
double ret;     // значение для теста
//Вывод содержимого каталога plaugins
  dir = opendir("../plagins");
  printf("Сейчас в каталоге находятся следующие библиотеки: ");
    while ((entry = readdir(dir)) != NULL)
    {
        if(entry->d_name==".so")
        printf("%s\n", entry->d_name);//загрузка plugin-а
    }
    closedir(dir);
 
printf("pervoe chislo ");
scanf("%lf",&i1);
 
printf("vtoroe chislo ");
scanf("%lf",&i2);
 
 
ext_library = dlopen("../plagins/libadd.so",RTLD_LAZY); //загрузка библиотеки
if (!ext_library)
    {
        //если ошибка, то вывести ее на экран
        fprintf(stderr,"dlopen() error: %s\n", dlerror());
        return 1;
    };
    //загружаем из библиотеки требуемую процедуру (в нашем случае она одна)
myPlugin1_calFunc=(double (*)(double a,double b))dlsym(ext_library,"calcFunc");
   if (myPlugin1_calFunc==NULL){
        fprintf(stderr,"dlsym error: not found symbol\n" );
        dlclose(ext_library);
        return 1;
    }
 ret=myPlugin1_calFunc(i1,i2);//вызываем функцию
    printf("answer:%f\n",ret);
    //закрываем библиотеку
    dlclose(ext_library);
    return 0;
}

Теперь проверяем, если файл является библиотекой, то считать из него функцию.То есть, лучше наверное сделать глобальную переменную, хранящую имя функции, которую она экспортирует. Имя переменной должно быть одинаково во всех библиотеках. И тогда, сначала нужно забрать переменную из библиотеки, а по ее значению, уже функцию. Я вот понимаю как это должно быть, ну то есть логику, а как конкретно реализовать пока не могу понять, опыта мало..

Добавлено через 1 час 25 минут
nikolay1982, фактически, можно конечно было бы сделать чтобы после вывода списка библиотек в папке plugins, пользователь набирал название библиотеки, и так как там одна функция, происходило бы открытие набранной библиотеки, загрузка этой единственной функции, вывод результата и закрытие библиотеки.
Но, я хочу сделать список функций, которые сейчас доступны из всех библиотек в папке plugins. То есть мне нужно создавать массив, в который я буду помещать названия библиотек(для того чтобы открыть их все) и массив в который я буду помещать названия находящихся в них функций(чтобы загрузить их в еще один массив), так?

Добавлено через 5 часов 42 минуты
nikolay1982, сделал вот так (костыли конечно, но заданию вроде соответствует)
Кликните здесь для просмотра всего текста
C
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <stdio.h>
#include <stdlib.h>
/* заголовочный файл для работы с динамическими библиотеками */
#include <dlfcn.h>
/* заголовочный файл для работы с opendir */
#include <dirent.h>
#include <string.h>
//Если вы хотите добавить свои библиотеки в папку plagins
//они должны называться lib***.so
int main(void)
{
    //Объявляем переменные
DIR *dir;
int i=0, ci=1;
 struct dirent *entry;
  double i1,i2;
   double (*myPlugin1_calFunc)(double a,double b);
    void *ext_library; // хандлер внешней библиотеки
     double ret;     // значение для теста
char library_name[20]="", *bibl=".so", *sravn, vvod[3]="", c;
char libr_nachalo[]="../plagins/lib";
char libr_konec[]=".so";
c=(char)(ci+'0');
while (1)
{
 switch(c)
 {
 case '1':
printf("Введите первое число ");
scanf("%lf",&i1);
 
printf("Введите второе число ");
scanf("%lf",&i2);
//Вывод содержимого каталога plaugins
  dir = opendir("../plagins");
  printf("Вы можете воспользоваться следующими функциями: \n");
    while ((entry = readdir(dir)) != NULL)
    {
        sravn=strstr(entry->d_name,bibl);
            if(sravn!=NULL)
            {
                for(i=3;i<6;i++)
                   printf("%c", entry->d_name[i]);//вывод названия функции
 
                    printf("\n");
            }
    }
    closedir(dir);
 
printf("Какой функцией вы хотите воспользоватся? \n");
    scanf("%9s", vvod);
        sprintf(library_name, "%s%s%s", libr_nachalo, vvod, libr_konec);
            //printf("%s\n", library_name);
 
ext_library = dlopen(library_name,RTLD_LAZY); //загрузка библиотеки
if (!ext_library)
    {
        //если ошибка, то вывести ее на экран
        fprintf(stderr,"dlopen() error: %s\n", dlerror());
        return 1;
    };
    //загружаем из библиотеки требуемую процедуру (в нашем случае она одна)
myPlugin1_calFunc=(double (*)(double a,double b))dlsym(ext_library,"calcFunc");
   if (myPlugin1_calFunc==NULL){
        fprintf(stderr,"dlsym error: not found symbol\n" );
        dlclose(ext_library);
        return 1;
    }
 ret=myPlugin1_calFunc(i1,i2);//вызываем функцию
    printf("answer:%f\n",ret);
    //закрываем библиотеку
    dlclose(ext_library);
 break;
 case '0': return 0;
 default : puts(" Error!");
 }
 puts(" 1 - продолжить ");
 puts(" 0 - выход");
 scanf("%d",&ci);
 c=(char)(ci+'0');
}
    return 0;
}
0
128 / 126 / 60
Регистрация: 22.01.2014
Сообщений: 464
11.04.2016, 17:31
Я же вам предлагал массив
C++
1
TPluginFunc funcs[100];
В TPluginFunc можно хранить и указатель на handle of library:

не надо ничего мудрить.
Один раз загружаем функции(при инициализации).
И один раз выгружаем функции(при выходе из программы)
C++
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//#include <unistd.h>
#include <dirent.h>
#include <dlfcn.h>
 
//#define TEST_INTER_FUNC_PTR 1
typedef double (*TCalcFunc)(double, double);
//Interface 
/*
    const char getCalcFuncName(); //возвращает имя реализованной в плагине функции
    int getCalcFuncArgumentCount();//возвращает количество элементов функции плагина
    double calFunc(double a,double b);//Сама функция плагина 
*/
typedef struct _TPluginFunc {
    void *      handle;//указатель загруженной библиотеки, аналогично  ext_library
    const char *    name;//Это имя нужно взять после загрузки библиотеки используя указатель,
        //на getCalcFuncName() см. интерфейс библиотеки-> см. ниже код
    double (*calcFunc)(double, double);     //Можно для упрощения создать тип этой функции
    //далее следуют другие указатели на функции
    //...
} TPluginFunc;
 
TPluginFunc funcs[100]; //глобально
int plugins_count = 0;  //кол-во загруженных плагинов
 
double mul_calFunc(double a, double b)
{
    return (a*b);
}
 
int load_plugins()
{
    DIR *dir;
    void *handle;
    int i;
    char fname[256];
    const char *op_name;
    struct dirent *entry;
    const char *(*funcName)(void);
    TCalcFunc calc_func=NULL;
    plugins_count = 0;
    const char *plugin_dir="./plugins";
        //"../plagins";//через U! plUgins! исправте сами 
    dir = opendir(plugin_dir);
    if (dir==NULL){
        fprintf(stderr, "Error!opendir failed!\n");
        exit(20);
        return 0;
    }
    //memset()
    for (i = 0; i < 100; i++){
        funcs[i].handle=NULL;
    }
    for (i = 0; i < 100; i++)
    {
        if ((entry = readdir(dir)) == NULL){
            break;
        } 
        printf("try load:%s\n", entry->d_name);//здесь просто вывод имени файла, вам же нужна загрузка plugin-а
        strcpy(fname,plugin_dir);
        strcat(fname,"/");
        strcat(fname,entry->d_name);
        printf("try dload:%s\n", fname);
        handle=dlopen(fname,RTLD_LAZY);        //загрузка библиотеки
        if (!handle) {
            //если ошибка, то вывести ее на экран
            fprintf(stderr, "dlopen() error: %s\n", dlerror());
            continue;
            //exit(1);
            //return (1);
        }
        funcName = (const char *(*)(void))dlsym(handle, "getCalcFuncName");
        if (funcName) 
        {   
            op_name =funcName();
        }else{
            fprintf(stderr,"\nError dlsym(handle, "getCalcFuncName")!");
            op_name="Unknow Function!";
        }
        calc_func=dlsym(handle,"calFunc");
        if (calc_func==NULL)
        {
            fprintf(stderr, "dlsym(handle,"calcFunc")  return NULL!\nError: %s\n", dlerror());
            dlclose(handle);
        }else{
            //OK load plugin
            funcs[plugins_count].handle=handle;
            funcs[plugins_count].name=op_name;
            funcs[plugins_count].calcFunc=calc_func;
            plugins_count++;
            printf("ok dload:%s\n", fname);
        }
 
    }
 
    closedir(dir); 
    return plugins_count;
}
int unload_plugins(){
    int i;
    for (i = 0; (i < plugins_count); i++){
        if (i>=100) break;
        if (funcs[i].handle) dlclose(funcs[i].handle);
        funcs[i].handle=NULL;
    }
    return 0;
}
int main(){
    double ret,a,b;
    double (*myPlugin1_calFunc)(double a, double b);
    if (load_plugins()==0){
        fprintf(stderr,"\nFailed load plugins!");
        return 1;
    }
    a=2.4;b=-0.3;
    printf("\ntry func[0].calc(%f,%f)\n",a,b);
#ifdef TEST_INTER_FUNC_PTR
    myPlugin1_calFunc = mul_calFunc;
#else
    myPlugin1_calFunc=funcs[0].calcFunc;//Для примера берем первыю загруженную функцию(плагин)
#endif
    ret=myPlugin1_calFunc(a,b);
    printf("\nok func[0].calc(%f,%f):return:%f\n",a,b,ret);
    unload_plugins();
        return 0;
}
Добавлено через 3 минуты
Простейщий плагин:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//возвращает имя реализованной в плагине функции
const char *getCalcFuncName()
{
    return ("+");
}
 
//возвращает количество элементов функции плагина
int getCalcFuncArgumentCount()
{
    return (2);
}
 
//Сама функция плагина
double calFunc(double a, double b)
{
    return (a+b);
}
Если надо bash скрипт для компиляции под MinGW(Windows), могу дать.
0
 Аватар для tarakan.nvkz
1 / 1 / 0
Регистрация: 10.09.2011
Сообщений: 146
13.04.2016, 11:26  [ТС]
Цитата Сообщение от nikolay1982 Посмотреть сообщение
Если надо bash скрипт для компиляции под MinGW(Windows), могу дать.
а в чем удобство? я сейчас работаю в виндовс, компилю/собираю в ubuntu. единственное что не нравится, я вот скомпилю прогу, а она не компилится, приходится всегда заново наюирать в терминале и т.п.
0
128 / 126 / 60
Регистрация: 22.01.2014
Сообщений: 464
13.04.2016, 12:16
Цитата Сообщение от tarakan.nvkz Посмотреть сообщение
единственное что не нравится, я вот скомпилю прогу, а она не компилится, приходится всегда заново наюирать в терминале и т.п.
Поэтому надо думать о том, что раз я много раз делаю одно и то же действие, а как же я могу оптимизировать процесс сборки, что бы в консоли не надо было 10 раз набирать одно и то же.

Для этого применяются скрипты bash (для новичков неплохо, не требуется многих знаний) и Makefile.
0
 Аватар для tarakan.nvkz
1 / 1 / 0
Регистрация: 10.09.2011
Сообщений: 146
13.04.2016, 12:21  [ТС]
nikolay1982, с другой стороны я так лучше разбираюсь, что я вообще делаю, запоминаю команды gcc..

Добавлено через 1 минуту
nikolay1982, еще, может посоветуете литературу, именно программирование в c под линукс? или можно иногда задавать Вам вопросы(если вас не затруднит конечно)?
0
128 / 126 / 60
Регистрация: 22.01.2014
Сообщений: 464
13.04.2016, 14:26
Цитата Сообщение от tarakan.nvkz Посмотреть сообщение
с другой стороны я так лучше разбираюсь, что я вообще делаю, запоминаю команды gcc.
Вы столько раз компилировали, и еще не запомнили 4 опции компилятора gcc?
Цитата Сообщение от tarakan.nvkz Посмотреть сообщение
посоветуете литературу, именно программирование в c под линукс?
Есть много разных книг (программирование под Linux).
Основы программирования в Linux (Мэтью);
Самоучитель программирование в Linux(Иванов);
Linux программирование в примерах(Роббинс):
Статьи Андрея Боровского (очень хорошо для новичков).
Эти источники не отменяют Linux/Posix man pages. Я использую manpages.chm(почти 5 Мб) (English) ( не помню, где скачал). Есть и на русском(частично), но в формате man. Если кто найдет manpages.chm на русском, то буду благодарен.
0
657 / 410 / 76
Регистрация: 21.09.2008
Сообщений: 1,411
13.04.2016, 19:52
Цитата Сообщение от nikolay1982 Посмотреть сообщение
посоветуете литературу, именно программирование в c под линукс?
Лучшая книга по технологии программирования на Си под *nix. В Сети есть скан весьма приличного качества, можно разыскать.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
13.04.2016, 19:52

Не могу переписать модель для калькулятора Swift 3.0.1
Есть данная рабочая модель калькулятораю: import Foundation class CalculatorHead { private var accumulator = 0.0 ...

Не работает программа (эквивалент калькулятора)
Всем доброго времени суток) Не могу понять почему программа не работает, если кто знает скажите, заранее спасибо)) #include...

Не могу собрать калькулятор
.model small .286 .data minus db '-$' error db 'ERROR! Division by zero',10,13,'$' vyvod dw ?,'$' znak dw ? ch1 dw ? ...

Не могу собрать проект
Помогите, пожалуйста, собрать проект в QT. С QT ни разу не работал. P.S. как сделать, чтобы QT писал об ошибках русскими буквами,а не...

Не могу собрать формулу
Всем Привет помогите пожалуйста содать функцию В ячейке C1:C22 написано цыфры мне нужно написать функцию чтобы автоматически вписывался...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Новые блоги и статьи
[golang] Конкурентный fetcher с ограничением максимального количества одновременных HTTP запросов.
alhaos 10.06.2026
Задача Реализовать конкурентный fetcher с ограничением максимального количества одновременных HTTP запросов. Сигнатура func Fetch(urls string, maxConcurrent int) Result Пример urls :=. . .
[golang] Состояние гонки (race condition)
alhaos 10.06.2026
Состояние гонки (race condition) Состояние гонки (Race Condition) — это ошибка, возникающая при одновременном доступе нескольких горутин к одним и тем же данным без должной синхронизации. При этом. . .
Взрослые отношения, и почему они не получаются
kumehtar 09.06.2026
Когда в детстве ребёнок не получает от родителей чего-то важного, он лишается не просто приятных переживаний, а основы для формирования определённых внутренних качеств и навыков. Если ребёнок не. . .
[golang] Worker Pool
alhaos 09.06.2026
Worker Pool Worker Pool — паттерн конкурентной обработки задач в Go. Суть: фиксированное количество горутин-воркеров читают задачи из общего канала и пишут результаты в общий канал результатов. . . .
[golang] Pipeline
alhaos 08.06.2026
Pipeline Pipeline — паттерн конкурентной обработки данных в Go. Суть: данные проходят через цепочку независимых стадий, каждая из которых работает в своей горутине и общается с соседями через. . .
Свет внутри себя
kumehtar 07.06.2026
Пусть это будет здесь lIs4oanZS9Y
Программа для com-порта
Uhbif79 05.06.2026
Всем привет, давно хотел изучить Qt, начинал, бросал, потом снова начинал. И сейчас вот смог написать свою первую программу. До этого имел опыт программирования микроконтроллеров, писал прошивки на. . .
Транскрипция 55-минутного видео через Whisper: WhisperDesktop облажался, спас Google Colab[
anaschu 01.06.2026
Понадобилось получить текст из свежезагруженного видео на YouTube. Казалось бы, задача на пять минут. Заняла полтора часа. Делюсь опытом — может кому пригодится последовательность решений. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru