Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: как запретить экспорт отдельных функций из lib  (Прочитано 14566 раз)
0 Пользователей и 1 Гость смотрят эту тему.
jur
Помогающий

lt
Offline Offline

« : 19-09-2011 17:45 » 

Ткнулся я в это дело... Пока отложил... Для начала поштудирую литературу. Я потом еще обращусь, хорошо?

Еще такой простейший вопрос. Я пишу здоровенную DLL-ку измерений разных УЗ-параметров. Чтобы она не принимала совсем уж непотребных размеров, я все измерения оформляю в виде отдельных LIB-проектов (Configuration Type: Static Library (.lib)), присоединяемых к основной DLL-ке на этапе ее линковки.

Черт, столкнулся с проблемой, что если имя функции в одной LIB-е совпадает с именем функции в другой - линкер связывает с первой встретившейся одноименной функцией. Как бы сделать так, чтобы все функции данной LIB-ы были как бы static на уровне данной конкретной LIB-ы и не цеплялись бы в другой LIB-е? Это возможно? Или заводить геморрой с дописыванием уникального префикса к каждой функции LIB-ы? (Делать их static неудобно, т.к. локальные функции LIB-ы должны быть видны в нескольких других ее файлах.)
Записан

MPEG-4 - в массы!
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 19-09-2011 18:22 » 

lib, это же то же самое что obj? линкеру пофиг откуда брать... может быть очередностью поиска имен при линковке поиграть. не знаю есть такая настройка? но это путаница полная будет...
так что по-моему никак, только через геморой. но может народ что подскажет.
либо не линковать их вместе - делать отдельные dll с последующей статической линковкой в общей dll.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 19-09-2011 18:28 » 

Ochkarik,
Цитата
делать отдельные dll с последующей статической линковкой в общей dll
При статической линковке думаю получится тоже самое что и с lib файлами. Моё мнение: сделать отдельные dll и потом подгружать нужные динамически через LoadLibrary. Таким образом можно будет получить указатели на функции в dll, что даст возможность использовать несколько dll одновременно без всяких конфликтов.
« Последнее редактирование: 19-09-2011 18:36 от RuNTiME » Записан

Любимая игрушка - debugger ...
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 19-09-2011 18:46 » 

А если вот такая ситуация возникнет: код DLL вызывает конфликтующие экспортируемые функции — что произойдет?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 19-09-2011 18:50 » 

с динамической... если оно там на самом деле не требовалось - просто неудобно. тот же геморой)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
jur
Помогающий

lt
Offline Offline

« Ответ #5 : 19-09-2011 18:53 » 

При статической линковке думаю получится тоже самое что и с lib файлами. Моё мнение: сделать отдельные dll и потом подгружать нужные динамически через LoadLibrary. Таким образом можно будет получить указатели на функции в dll, что даст возможность использовать несколько dll одновременно без всяких конфликтов.

В том-то и дело, что не хочется городить более двух десятков DLL-ок :-)

А как сделать статическую линковку DLL-ки? Может на самом деле получится, ведь, насколько я понимаю, в проекте DLL все локальные связи уже слинкованы при Rebuild Solution, или нет?
Записан

MPEG-4 - в массы!
RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 19-09-2011 18:58 » 

jur,
Цитата
Может на самом деле получится, ведь, насколько я понимаю, в проекте DLL все локальные связи уже слинкованы
Локальные связи слинкованы, главное чтобы имена экспортируемых функций не совпадали во всех библиотеках...
Записан

Любимая игрушка - debugger ...
jur
Помогающий

lt
Offline Offline

« Ответ #7 : 19-09-2011 19:12 » 

Сейчас у меня сделано так:

- все DLL-ки имеют по три одинаковых имени экспортируемых функций (чтобы LoadLibrary не заморачивалась).
- модуль, управляющий загрузкой DLL-ок, получает имя файла, грузит соответствующую DLL-ку и сохраняет адреса трех ее функций.
- дальнейшая работа идет через эти адреса, т.е. основной DLL-ке без разницы, с каким именно измерением ей работать.

Просто мне не хотелось городить кучу отдельных DLL-ок :-)
Записан

MPEG-4 - в массы!
RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 19-09-2011 19:41 » 

jur, Вот такая идея родилась:
Код: (C++)
// типы описывающие функции интерфейса библиотеки
typedef void (*fun1_t)(int i);
typedef void (*fun2_t)(float f);
typedef void (*fun3_t)(double d);

// описание интерфейса библиотеки
typedef struct {
    fun1_t f1;
    fun2_t f2;
    fun3_t f3;
} lib_interface_t;

// человекопонятные названия библиотек
enum {
    lib1_interface,
    lib2_interface,
    lib3_interface,

// -------------------
    num_of_libraries
};

// массив для хранения интерфейсов библиотек
extern lib_interface_t lib_interfaces[num_of_libraries];

// где - то при инициализации программы
void init_library_interfaces() {
    lib_interfaces[lib1_interface].f1 = <указатель на функцию 1>
    lib_interfaces[lib1_interface].f2 = <указатель на функцию 2>
    lib_interfaces[lib1_interface].f3 = <указатель на функцию 3>
    ...
    // аналогичная инициализация остальных библиотек
}

// где - то, где нужно получить доступ к интерфейсу библиотеки
void foo() {
    lib_interface_t *lib_iface = lib_interfaces[lib1_interface];

    lib_iface->f1(1);
    lib_iface->f2(2.3);
    lib_iface->f3(5.99999999);
}

Если использовать такой метод, можно не городить кучу dll'ок, все останется в lib'ах. Это примерная реализация на Си... На плюсах можно чего нибудь покрасивее придумать Улыбаюсь

При этом конечно же делаем уникальные имена функций во всех lib'ах...
« Последнее редактирование: 19-09-2011 19:47 от RuNTiME » Записан

Любимая игрушка - debugger ...
jur
Помогающий

lt
Offline Offline

« Ответ #9 : 19-09-2011 19:55 » 

Во, во! Значит я правильно делаю, т.к. именно так у меня и есть! :-) Прям один к одному:

Код:
#define PARAM_HEADER_CHARS  40
#define PARAM_HEADER_EMPTY  "<Header empty>"

typedef struct {
  LPCTSTR Param_section;  // Param's section name in "Biometry.ini"
  TCHAR   Param_header[PARAM_HEADER_CHARS];
  void    (*Param_Start) ();
  void    (*Param_Close) ();
  BOOL    (*Param_SleKey_Pressed) (BYTE sle_key);
} PARAM_INTREFACE, *PPARAM_INTREFACE;

const PARAM_INTREFACE Param_Interfaces[] =
{
  { BIOMETRY_MEAS_LINEAR_B, PARAM_HEADER_EMPTY, LinearB_Start, LinearB_Close, LinearB_SleKey_Pressed },
  { BIOMETRY_MEAS_BPD,      PARAM_HEADER_EMPTY, BPD_Start,     BPD_Close,     BPD_SleKey_Pressed     },
};

const DWORD Number_of_params = sizeof(Param_Interfaces) / sizeof(Param_Interfaces[0]);

И все было бы хорошо и жизнь казалась бы прекрасной, но... У меня во всех модулях измерений есть локальные функции, вроде:

void FuncBar_Start();
void FuncBar_Close();
void Trackball_Start();
void Trackball_Close();
и т.д. и т.п.

Вот их-то мне и нужно изолировать. Т.е. FuncBar одного измерения устанавливает свои обработчики на F1...F8, FuncBar другого - свои. А сейчас они все устанавливают FuncBar для первого попавшегося измерения параметра! :-)
Записан

MPEG-4 - в массы!
RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 19-09-2011 20:08 » 

jur, Если не принципиален чистый Си, то можно попробовать для каждой библиотеки создать свою область имён. В таком варианте конфликт не возникнет.
Код: (C++)
namespace library1 {
    void FuncBar_Start();
    void FuncBar_Close();
    void Trackball_Start();
    void Trackball_Close();
}

namespace library2 {
    void FuncBar_Start();
    void FuncBar_Close();
    void Trackball_Start();
    void Trackball_Close();
}
Записан

Любимая игрушка - debugger ...
jur
Помогающий

lt
Offline Offline

« Ответ #11 : 19-09-2011 20:14 » 

Спасибо! Здорово! Попробую (но уже завтра, если сегодня зацеплюсь - только под утро спать лягу :-)

Но я с этими "namespace" как-то не сталкивался... Надо полагать, что namespace нужно указать в начале каждого CPP-файла? Или можно просто в "stdafx.h" занести?
Записан

MPEG-4 - в массы!
RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 19-09-2011 20:24 » new

jur, нужно указывать и в cpp и в заголовках. В stdafx.h не нужно. Например:

Код: (C++)
// library1.h

namespace library1 {
    void FuncBar_Start();
    void FuncBar_Close();
    void Trackball_Start();
    void Trackball_Close();
}


// library1.cpp

namespace library1 {

void FuncBar_Start() {
}

void FuncBar_Close() {
}

void Trackball_Start() {
}

void Trackball_Close() {
}


} /* namespace library1 */

А вообще советую тогда почитать про пространства имен C++: http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%B0%D0%BD%D1%81%D1%82%D0%B2%D0%BE_%D0%B8%D0%BC%D1%91%D0%BD_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)
Записан

Любимая игрушка - debugger ...
jur
Помогающий

lt
Offline Offline

« Ответ #13 : 19-09-2011 21:36 » 

Спасибо! Работает! Даже поспать еще успею... ;-)
Записан

MPEG-4 - в массы!
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #14 : 20-09-2011 03:18 » 

При статической линковке думаю получится тоже самое что и с lib файлами. Моё мнение: сделать отдельные dll и потом подгружать нужные динамически через LoadLibrary. Таким образом можно будет получить указатели на функции в dll, что даст возможность использовать несколько dll одновременно без всяких конфликтов.
насколько я помню, из DLL надо явно экспортировать интерфейс, а всё что внутри DLL (на винде) будет изолировано внутри

И да пространства имён рулят. для того и делали
Записан

Странно всё это....
jur
Помогающий

lt
Offline Offline

« Ответ #15 : 20-09-2011 05:44 » 

Я так понял, что если делать так, как описано в посте "Ответ #12", то получится вроде того, если бы я просто приписал какой-то префикс (к примеру "library1_") ко всем функциям и глобальным переменным, заключенным в фигурные скобки. Но с namespace гораздо удобнее, да и красивее.

Большое спасибо, друзья, за помощь!
Записан

MPEG-4 - в массы!
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines