Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.135.219.166] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Вопрос не про язык,а про линковку. В частности линковку через link.exe студийный или lld-link из LLVM
Есть MyDll1.lib в которой объявлена функция MyFunc Есть MyDll2.lib в которой объявлена функция с таким же именем MyFunc Исходники либ недоступны. И есть проект, который хочет статически слинковаться с обоими dll'ками и использовать эти функции. Собственно вопрос, КАК ?? В дельфе подобное делается пример так: function MyFunc1: Integer; extrenal 'MyDll1.dll' name 'MyFunc'; function MyFunc2: Integer; extrenal 'MyDll2.dll' name 'MyFunc'; В C# (но тут не совсем корректное сравнение, .NET AFAIR динамически dll грузит) [DllImport("MyDll1.dll.dll", EntryPoint = "MyFunc")] public static extern int MyFunc1(); [DllImport("MyDll2.dll.dll", EntryPoint = "MyFunc")] public static extern int MyFunc2(); |
Сообщ.
#2
,
|
|
|
Цитата jack128 @ И есть проект, который хочет статически слинковаться с обоими dll'ками и использовать эти функции. Собственно вопрос, КАК ?? В дельфе подобное делается пример так: function MyFunc1: Integer; extrenal 'MyDll1.dll' name 'MyFunc'; function MyFunc2: Integer; extrenal 'MyDll2.dll' name 'MyFunc'; jack128, так мы же не знаем, что на самом деле делает Дэлфи или C#. Возможно, обнаружив соотв. строки они явно грузят dll, узнают адреса требуемых функций и присваивают их значения указателям с другими именами. Само присутствие вышеприведённых строк как бы намекает на это. |
Сообщ.
#3
,
|
|
|
Создаём два DEF-файла. MyDll1.def
LIBRARY MyDll1 EXPORTS MyFunc1 = MyFunc LIBRARY MyDll2 EXPORTS MyFunc2 = MyFunc Если DLL уже в наличии и нет возможности их пересобрать, то вместо компиляции в DLL используем lib для получения библиотек импорта прямо из DEF. Но что-то из глубин памяти мне подсказывает, что MSный lib делает это криво и не переименовывает. Возможно, понадобится поискать другие инструменты, безглючные. |
Сообщ.
#4
,
|
|
|
Так, наверно я неправильный термин использовал. Не статическая линковка, а статическая загрузка. Тут используют термины implicit linking, static load or load-time dynamic linking. В общем когда линкер при генерации exe прописывает в таблицу импорта названия dll'ек/функций в этих dll'ках. Никаких адреса, как и сами dll при сборке приложения при таком подходе не нужны. Нужны только название dll и название функций.
Добавлено Цитата Qraizer @ Создаём наши DLL с указанием этих DEF DLL сторонние, пересобрать я их не могу Добавлено Цитата Qraizer @ то MSный lib делает это криво и не переименовывает. Ага. Возможно. Я как раз по предложенной тобой схеме пребывал, у меня не получилось. В комплекте llvm наверняка есть аналог lib. Поищем. |
Сообщ.
#5
,
|
|
|
Цитата jack128 @ Та не, это было понятно. Есть такая штука, как библиотека импорта, и вот она, в отличие от просто библиотеки, в которой функции и данные, как раз описывает ссылки на импортируемые из DLL функции и данные. Ну, т.е. библиотека по любому какая-то есть, но для связи с DLL используется некий особый её формат. (На самом деле нет, просто там другие атрибуты у связываемых сущностей, но не суть.) Эту библиотеку как-то надо получить, и проще всего это делается прямо при сборке самой DLL, линкер её автоматом создаёт. Тут даже DEF очень часто необязателен, т.к. линкеру все экспортируемые имена известны, он же как раз эту DLL собирает. И только в особых случаях, типа твоего, DEF-таки нужен. Но в твоём случае это не подходит, так что нужно использовать не "линкер", а "библиотекарь", но скармливать ему нужно всё тот же DEF, где всё описано.В общем когда линкер при генерации exe прописывает в таблицу импорта названия dll'ек/функций в этих dll'ках. Никаких адреса, как и сами dll при сборке приложения при таком подходе не нужны. Нужны только название dll и название функций. P.S. В крайнем случае можно написать свою DLL-прокси. В ней сделать функции с разными именами, а каждая из них будет динамически звать нужную из нужно DLL. К ней будет легко присобачить статическую загрузку, а то, что она внутри использует динамическую, будет скрыто и не мешает. |
Сообщ.
#6
,
|
|
|
Цитата Qraizer @ EXPORTS MyFunc1 = MyFunc Нет, это не подходит. Эта штука описывает таблицу экспорта и используется при сборке библиотеки. Пусть у нас есть есть 1.obj в котором сидит функция MyFunc. тогда подсунув линкеру объектник и def файл (link /dll 1.obj 1.def) теоретически можно получить dll c экспортируемой функций MyFunc1. И в lib файле будет сидеть MyFunc1. Насколько я понял, в синтаксисе def есть секция IMPORTS (см тут), но применить её у меня пока не получается. lib ничего про неё не знает по крайней мере Цитата Qraizer @ P.S. В крайнем случае можно написать свою DLL-прокси. В ней сделать функции с разными именами, а каждая из них будет динамически звать нужную из нужно DLL. К ней будет легко присобачить статическую загрузку, а то, что она внутри использует динамическую, будет скрыто и не мешает. да понятно, что костылей можно нагородить всяких. Но это не наш метод. |
Сообщ.
#7
,
|
|
|
Цитата jack128 @ Подходит. При сборке DLL линкер обычно тут же создаёт библиотеку импорта .LIB к ней, да, но библиотеку импорта можно получить и без построения .DLL, только лишь на основе .DEF, я именно это и предложил. А .DEF в свою очередь можно получить с помощью какого-нибудь dumpbin или любой другой утили, что покажет весь экспорт этой .DLL Нет, это не подходит. Эта штука описывает таблицу экспорта и используется при сборке библиотеки. Добавлено Цитата jack128 @ Вот чем-чем, а импортом никогда не пользовался. Если я правильно его понимаю, такой DEF ты должен применить к своему приложению, а не библиотекам, так что lib тут будет ни причём Насколько я понял, в синтаксисе def есть секция IMPORTS (см тут), но применить её у меня пока не получается. lib ничего про неё не знает по крайней мере Добавлено P.S. Проверил MSный lib. Баг в натуре есть. Открыл проблему в саппорте, жду разъяснений. Не исключено, что мне расскажут, какой я дебил, посмотрим. |
Сообщ.
#8
,
|
|
|
Цитата Qraizer @ Открыл проблему в саппорте, жду разъяснений А ссылочка публичная есть?? |
Сообщ.
#9
,
|
|
|
Цитата jack128 @ да понятно, что костылей можно нагородить всяких. Но это не наш метод. Попробовать отредактировать эксторт и .lib - файл одной из dll. Вручную заменить имя проблемной функции. |
Сообщ.
#10
,
|
|
|
Цитата jack128 @ lib.exe does not rename export names from DLL when renaming requested by .DEF or /EXPORT: command line option. А ссылочка публичная есть?? |
Сообщ.
#11
,
|
|
|
Цитата jack128 @ Исходники либ недоступны. И есть проект, который хочет статически слинковаться с обоими dll'ками и использовать эти функции. Собственно вопрос, КАК ?? jack128, совсем не понятно, в чём проблема. Если ты не из старт-апа собрался вызывать функции dll, тогда: Предположим, статически слинковались с dll. В каждой dll полно своих функций, но есть одна проблемная - с одинаковым именем. При старте приложения обе dll загружены в память. 1. Получим на них handle. 2. Получим адреса на процедуры с проблемными именами. 3. Присвоим адреса указателям (с уникальными именами) на процедуры. Это всё. Не исключено, что Дэлфи делает именно это. |
Сообщ.
#12
,
|
|
|
Хм. Баг в lib.exe подтверждён. Уже хорошо. Жаль, что так поздно, если мне не изменяет память, ему около десяти лет как минимум.
ЫукпШ, статически слинковать не получится. Хороший линкер даст эррор о множественном определении, но это если хороший. В точки зрения Стандарта языка мы тут имеем нарушение ODR, т.к. одна и та же сущность определена по-разному, а это "всего лишь" неопределённое поведение, не обязательно долженствующее быть обнаруженное средствами разработки. |
Сообщ.
#13
,
|
|
|
Цитата Qraizer @ ЫукпШ, статически слинковать не получится. Хороший линкер даст эррор о множественном определении, Qraizer, я просто проверил это. Простым как табуретка тестом (случайно была заготовка). Всё получится. Что касается определения "хороший линкер". Тут я никак не могу согласиться. Если функции с одним именем имеются в наличии в разных dll, то это разные сущности - однозначно. Доступ к ним должен быть обеспечен, что и происходи в действительности. И то, что возникают потенциальные проблемы в из использовании скорее недостаток компилятора. В Дэлфи решение простое и удобное. Но можно и получше придумать - но не сделали. Для разрешения таких конфликтов предназначен "namespace". Скрытый текст Например, взять и разрешить окружать описанные функции из dll namespace-ом. С тем, чтобы иметь возможность массового переименования всех dll-ных функций для конкретного приложения. Или как то так: namespace SomeDll { #pragma comment(lib,"SomeDll.lib") } А для с++ надо знать пару функций WinApi. |
Сообщ.
#14
,
|
|
|
ЫукпШ, ты можешь как угодно с любых сторон рассматривать то, что можешь себе представить.
Цитата ЫукпШ @ Твоё представление о том, как правильно, никоим образом не меняет положений Стандарта языка. В нём есть правило одного определения. Точка. DLL с разными функциями, имеющие одинаковые имена, это правило нарушают. На этом всё.Что касается определения "хороший линкер". Тут я никак не могу согласиться. Если нет, то попробуй слинковать с приложением две функции с одинаковыми именами из разных библиотек. Простых lib, не dll. Хочешь тестов? Я тебе их накидаю три варианта. Один будет звать дважды одну и ту же, другой другую, третий оба раза разные. Обтестироваться можно будет по полной программе: неопределённое поведение по всей красе. Цитата ЫукпШ @ Чтобы они стали разными, их имена должны различаться. Для этого существует квалификация. Для экспортируемых из DLL функций этого сделано не было их авторами, а сырцов нет.Если функции с одним именем имеются в наличии в разных dll, то это разные сущности - однозначно. Цитата ЫукпШ @ Это недостаток структурного WinAPI. В объектом COM такого нет, там любой метод квалифицирован именем его интерфейса.И то, что возникают потенциальные проблемы в из использовании скорее недостаток компилятора. DLL ничем не отличаются от LIB, они точно также являются частью загруженного приложения. И на них в полной мере распространяется ODR. Не можешь обеспечить разделение сущностей по уникальным именам, получишь UB. А то, что их можно разделить динамической загрузкой, никому не новость, вот только jack128 это не устраивает. Добавлено Цитата ЫукпШ @ Оно делает ровно то же, что и решение с DEF, только средствами языка, а не ОС. В Дэлфи решение простое и удобное. |
Сообщ.
#15
,
|
|
|
Цитата Qraizer @ Это недостаток структурного WinAPI. В объектом COM такого нет, там любой метод квалифицирован именем его интерфейса. Это недостаток конкретно линкеров. В секции импорта любая функция квалифицирована именем dll. |