Помогите со статической загрузкой Dll

Тема в разделе "LANGS.C", создана пользователем Praetor11, 11 окт 2009.

  1. Praetor11

    Praetor11 New Member

    Публикаций:
    0
    Регистрация:
    11 окт 2009
    Сообщения:
    80
    Всем привет!

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

    Собственно вопросов у меня 2 и оба связаны с C++ и компилятором от gnu (gcc,as,ld,g++ -такая связка, среда Dev-C++, но это уже не важно)

    Вопрос 1: Как произвести статическое присоединение dll-библиотеки к моей программе. У меня есть длл, def-файл к ней и lib-файл к ней (все создано вместе соотвествующими опциями линкера) В длл есть функции объявленные как export "C" __declspec(dllexport).
    Хочу вызвать эти функции из программы ( через __declspec(dllimport)) Прошу не рассказывать мне о динамической загрузке через ЛоадЛибрери и о советах для компилятора от микрософат с его прагмами (#pragma comment (lib, "some.lib') - в gcc такое не катит). Если можно ответьте конкретным примером, что мне указать в коде/опциях компилятора или линкера.

    Вопрос 2: Как заставить компилятор не всовывать в мой код при компиляции вызовы функций __main и _alloca. Запускаю при опциях: -nostdlib -nostartfiles -nodefaultlibs (пробовал даже -ansi - вописании к gcc указано что тогда _alloca не является станд. фу-ей, но и это не помогает), точка входа давно сменена через -e _start, но в текст моей функции main (причем запуск уже идет с start!!!) компилятор упорно добавляет мне этот хлам, на что линкер потом ругаеца, потому что обе этих функции в libgcc.a, и приходится компилить с флагом -S, удалять строки вызова этих функций и потом линковать вручную. Не то чтобы это сильно напрягало, но вдруг есть способы отучить компилятор от этого пристрастия((

    Заранее спасибо!
     
  2. Praetor11

    Praetor11 New Member

    Публикаций:
    0
    Регистрация:
    11 окт 2009
    Сообщения:
    80
    О! Ответа на второй вопрос я хотя и не нашел, зато нашел метод его обхода. Тупой компилятор от gcc тупо вставляет вызов __main в функцию с именем main, но если такой функции в коде нет, то он не вставляет эту муть..Ура. Наконец-то можно не редактировать asm-код.

    А вот вопрос о статической загрузке пока не решен. Пробовал переименовывать dll.lib в libdll.a и подключать в самом линкере -ldll но ошибка о ненайденной ссылке на мою функцию остается. Может быть просто не может обнаружить её имя в библиотеке. Т.к. когда объявляю extern "C" DLLIMPORT он кричит что не нашел функцию _fun_name, но если убрать extern "C" не может найти _Z8fun_name, а если дописать _cdecl то там ещё сложнее. В самой длл функции объявлены как extern "C", в dll.lib их имена встречаются дважды, один раз как _fun_name, второй как __fun_name. Перебровал уже кучу способов. Пока не помогло. А зачем там вообще файл .def надо?
     
  3. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    Хехе, а ты, умный человек, знаешь, зачем он её туда вставляет?
     
  4. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    1. 1) К исходному тексту программы подключить файл, содержащий
    определения функций, которые реализованы в DLL.

    2) В командной строке gcc (например, в самом конце)
    кроме всего прочего указать путь к LIB-файлу.
     
  5. Praetor11

    Praetor11 New Member

    Публикаций:
    0
    Регистрация:
    11 окт 2009
    Сообщения:
    80
    Ну хоть человек я и не умный, но догадываюсь: для инициализации статических конструкторов классов. Только вот когда я указываю сборку с -nostdlib, а функция __main вызывает ф-цию из libgcc.a, линкер пошлет меня куда подальше. А самое главное, что классов у меня вообще нет (ни у меня, ни в подключаемых библиотеках), а майн все равно подшивается. В связи с вышеуказанным считаю действия компилятора нелогичными.

    Вы имеете в виду файл .def? Если да, то как именно его подключить? Я пробовал через #include и через #import, но компилятор ругается, что синтаксис не распознан и на каждую строчку этого файла выдает syntax error.

    Ну это первое что я делаю, вот только самому gcc этот файл даром не нужен, он нужен линкеру чтобы собрать приложение, правда сам файл .lib ему передать нельзя, т.к. он принимает через -lname (lib+name+.a имя файла) Я переименовал либ-файл, подключил таким образом но экспортируемые из библиотеки функции он так и не нашел( Возможно это из-за несовпадения имен. Но и в длл и в программе, функции объявляю как extern "C" (когда не объявляю их таковыми результат тот же). Все-таки гцц ацтой(
     
  6. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    Да нет, конечно, я имею ввиду .h - файл.
     
  7. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    Вот, допустим, у вас есть динамическая библиотека в которой реализованы
    некоторые функции, статическая библиотека, прилагающаяся к ней,
    заголовочный файл с определениями (прототипами) функций.
    Программа (исходный текст), которая использует динамическую библиотеку.
    Тогда скомпилировать все это дело можно так:
    Код (Text):
    1. gcc -I<путь_к_папке_include> -c -o objfile.o srcfile.c
    2. gcc -o exefile.exe objfile.o -L<путь_к_lib_файлам> -l<библиотака_0> -l<библиотака_1> ... <-l<библиотака_n>
    3.  
    4. примечание: имена статических библиотек указываются без расширений.
     
  8. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    Естественно, чтобы программа работата, нужно, чтобы DLL-библиотека
    находилась в папке с EXE-файлом. (или, например, в системной папке - windows, windows\system32).
     
  9. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    main никак с классами не связан - это главная программа, то с чего начинается выполнение.
    Да и библиотека libgcc по-моему к классам никакого отношения не имеет, библиотеки с++ по-другому называются .

    http://ru.wikipedia.org/wiki/DLL
    http://www.progz.ru/forum/index.php?showtopic=40362&st=0&p=184930&#entry184930
    И вроде никаких def не нужно для подключения DLL. def нужен при построении своей DLL.
     
  10. Praetor11

    Praetor11 New Member

    Публикаций:
    0
    Регистрация:
    11 окт 2009
    Сообщения:
    80
    Заголовочника от библиотеки у меня нет (т.к. писал её сам) но я объявляю импортируемые из неё функции прямо в срр файле.

    Вот, так я и делаю. файл DLL.lib переименовал в libDLL.a, чтобы можно было так подключить. DLL.lib получена при создании самой DLL опцией линкера --out-implib. Возможно, не та что нужна, но сравнивания содержимое этого файла со стандартным libkernel32.a заметил, что они очень схожи.

    в длл есть функция:

    Код (Text):
    1. extern "C" __declspec(dllexport) int SomeFunc(int a, int b);
    В файле DLL.lib её имя встречается один раз как _SomeFunc, и ещё один раз как __imp__SomeFunc.

    В файле программы объявляю эту функцию:

    Код (Text):
    1. extern "C" __declspec(dllimport) int SomeFunc(int a, int b);
    В опции добавляю: -L"parh" -lDLL (ну чтобы подключить libDLL.a). В итоге линкер выдает ошибку: не могу найти функцию __imp__SomeFunc.

    Если убирать extern "C", то имена ф-ций выглядят по-другому, но смысл тот же. В DLL.lib есть такое имя, а линкер не может его найти. При просмотре таблицы экспорта библиотеки функция имеет имя SomeFunc, безо всяких дополнительных символов.
    И ещё: При динамической линковке все отлично, когда использую это:

    Код (Text):
    1. GetProcAddressA(LoadLibraryA("DLL.dll"), "SomeFunc");
    Адрес возвращается нормально, и функция прекрасно работает.

    Кстати, в libkernel32.a имена API выглядят так: _LoadLibrary@4 (где после собаки идет число байт параметров)

    Уже не один день бьюсь над этой фигней(, могу прислать вам и dll и .lib, мб проблема в них.

    Точку входа можно установить на любую функцию программы)) и вообще я говорил не про main, а про __main. И библиотеки С++ для gcc именно так и называются (lib<name>.a), именно в них и заключены функции getch, malloc, printf и т.д. (хотя я не сильно разбирался, возможно там просто ссылки на библиотеку msvrt80.dll)

    По второй ссылке: очень хорошая ссылка, набрав неделю назад свой вопрос в гугле её прочитал одной из первых. К сожалению, там для Borland C++ и Visual C++. И совет типа "уберите галочку" у меня не прокатит. Кстати как выполнить совет "указать компилятору, что добавлять символ подчеркивания не следует!" на gcc я тоже не нашел, он все равно его ставит.
    Столь красивые и изящные прагмы для линкера:

    Код (Text):
    1. #pragma comment(linker, "/export:getSum=?getSum@@YAHHH@Z")
    на gcc тоже не катят. Впрочем имена экспортных функций при extern "C" он не меняет! В def-файле они чистенькие.

    Что касается первой ссылки на вику:

    Эта фраза без примера повергла меня в ступор. Мне что подключать dll.o к линковке? Но тогда это будет уже часть моей прграммы а не вызов из длл. Или под словами объектный модуль тут имеется в виду что-то другое?
     
  11. Praetor11

    Praetor11 New Member

    Публикаций:
    0
    Регистрация:
    11 окт 2009
    Сообщения:
    80
    Все. Вопрос решился методом проб и ошибок. Оказалось, что расширение .lib для линкера ld такое же подходящее как и .a. Линковать прогу он согласился только когда я подключил файл DLL.lib так: -lDLL.

    Честно говоря, я не могу подумать что это прокатит, потому что в документации к линкеру http://sourceware.org/binutils/docs-2.18/ld/index.html#Top
    про опцию -l черным по белому написано, что данная опция подключате файл так:
    -lname -> lib+name+.a

    А тут оказывается что и -lname -> name + .lib работает (причем так и нужно). Кстати явное указание расширения стало причиной моих неоднократных ошибок -lDLL.lib не работало(

    Кароче вывод такой: больше пробуем - меньше читаем документацию..
     
  12. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    ну дык, порт же.