Общая библиотека оболочки Windows не работает

Обновлено: 03.07.2024

«Я проверил /usr/local/lib, файлы там. У вас есть предложение?»

Ах да, классическая проблема при создании программного обеспечения. Проблема здесь в том, что libev установил себя в /usr/local/lib:

… но динамический компоновщик не знает, где они находятся, потому что никогда не слышал о /usr/local/lib. /usr/local — это традиционное место для установки дополнительных программ, поэтому они не мешают работе системных библиотек. Если вы работаете с фоном Windows, файлы .so по сути эквивалентны библиотекам DLL и загружаются при выполнении программы, которая от них зависит. Программы, использующие динамические библиотеки, имеют ряд преимуществ, заключающихся в том, что они меньше по размеру, а библиотеки можно обновлять без необходимости перекомпилировать все программы, которые от них зависят. Поэтому, если есть проблема безопасности с libev, вы можете просто исправить libev, и вам не придется пересобирать все, что использует эту библиотеку.

Вы можете увидеть, с какими библиотеками программа динамически связана, с помощью команды «ldd»:

Это подтверждает, что мы имеем дело только с новой библиотекой, а не с какой-то другой проблемой. Круто.

Неоптимальные исправления/ужасные идеи[0]

<р>1. Установите библиотеки в /usr/lib вместо /usr/local/lib. Мне это очень не нравится, потому что вы устанавливаете дополнительное программное обеспечение в системный каталог и можете вызвать конфликт, перезаписать уже существующую библиотеку и/или дестабилизировать другие части системы. Люди жалуются на нестабильную работу Windows, и именно из-за этого она становится нестабильной — установщики постоянно перезаписывают системные библиотеки DLL своими собственными. Последние версии Windows прилагают массу усилий, чтобы установщики не делали этого. Если вам скучно, поищите подсистему WinSxS, которую Microsoft создала для решения этой проблемы. В Linux нет ничего для решения этой проблемы, он просто предполагает, что вы знаете, что делаете. Такова сила UNIX. Вот веревка, постарайся не повеситься.

Когда вы создаете программное обеспечение с открытым исходным кодом под ОС UNIX, вы часто используете команду «настроить». Вы можете изменить место установки программного обеспечения, используя флаг «префикс»:

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

Очевидно, замените libev.so.4 правильным именем файла. Команда «ldconfig» обновляет кеш динамических библиотек системы, чтобы увидеть измененные библиотеки.

Тем не менее, не делайте этого. Плохой системный администратор.

Со всеми этими идеями вы также, скорее всего, столкнетесь с разницей между 32-разрядными и 64-разрядными версиями в более новых ОС, где 32-разрядные библиотеки находятся в /usr/lib, а 64-разрядные — в / usr/lib64. Это может сработать, а может и не сработать, но лучшие способы намного проще.

Идея получше

<р>4. Установите переменную среды LD_LIBRARY_PATH так, чтобы она указывала на /usr/local/lib. Если вы новичок в UNIX/Linux и не знаете, какую оболочку вы используете, используйте команду «ps», чтобы увидеть запущенные процессы:

Эй, смотрите, я запускаю tcsh, поэтому мое решение будет таким:

и я могу поместить эту команду в ~/.cshrc, чтобы она выполнялась при входе в систему.

Если ps сообщает, что вы используете bash:

и вы можете поместить это в свой файл ~/.bashrc, чтобы он всегда был там.

Изменение среды является делом каждого пользователя, поэтому это должны будут сделать другие пользователи в системе, или вам нужно поместить исправления в /etc/bashrc или /etc/csh.cshrc, широкие сценарии входа. Однако это исправление полезно, если у вас нет привилегий root в системе и/или вы хотите установить что-то в свой собственный домашний каталог.

Абсолютно простое, лучшее решение[2]

<р>5. Если у вас есть привилегии суперпользователя на этом компьютере с Linux, почему бы просто не попросить динамического компоновщика также проверить /usr/local/lib? Отредактируйте файл /etc/ld.so.conf и добавьте «/usr/local/lib» в отдельную строку внизу[3]. НЕ УДАЛЯЙТЕ ВЕЩИ ИЗ ЭТОГО ФАЙЛА. Когда вы закончите, это может выглядеть примерно так:

или он может выглядеть совершенно иначе, за исключением последней строки. Запустите ldconfig, чтобы обновить кеш:

Вы можете проверить свою работу с помощью:

Теперь вы должны увидеть содержимое /usr/local/lib, и ваш двоичный файл работает. Мальчик, это было легко, и вы не создавали себе дополнительную работу в будущем, дестабилизируя систему, перезаписывая системные файлы или оставляя уязвимости безопасности. Круто.

[0] Так почему же я перечислил плохие идеи? Потому что вы увидите все, что предлагается в качестве исправления людьми, претендующими на звание экспертов[1]. Я надеюсь, что вы поймете, почему это плохие идеи, почему они могут потребовать от вас больше работы в долгосрочной перспективе, и сможете принять взвешенное решение.

[1] Я не эксперт, я человек, который много этим занимался и мог бы ответить на ваш вопрос.Если кто-то называет себя экспертом, бегите прочь.

[2] Не гарантируется, что он будет простым или лучшим. Хотя мне это нравится.

[3] Если вы не можете редактировать в командной строке, попробуйте «nano». Это простой редактор, который часто устанавливается. Другой вариант — «vi», но он загадочен, и вы можете использовать Google, чтобы найти учебник, если он вам нужен. Преимущество vi в том, что он всегда установлен.

Я пытаюсь создать общую библиотеку, т. е. .so, из кода C++, используя оболочку Git Bash в Windows 10. Я использую Makefile для компиляции кода C++ в Windows 10. Запуск make через оболочку Git bash. Код компилируется без проблем и без сбоев создает объектные файлы. Но это не удается при создании файла .so, выдающего следующую ошибку. Ниже приведена часть Makefile, в которой целевая VLIB_SHARED_LIBRARY вызывает эту ошибку.

Тот же Makefile отлично работает в реальной ОС Linux Ubuntu, но не работает в Windows 10. Как исправить эту ошибку?

Вы должны показать нам правило или make-файл. Мне это кажется крайне странным. Стоит отметить, что использование имен путей с пробелами в make и make-файлах — верный путь к множеству проблем, и этого следует избегать. Если вы не можете избежать их, то вам, по крайней мере, нужно правильно указывать пути. Также, пожалуйста, используйте правильное форматирование StackOverflow в своем вопросе (вставьте как примеры кода, не жирным шрифтом).

Это не имеет ничего общего с Git. «Git bash» — это порт bash, который Git использует, но он не является частью Git. Я обновил ваши теги. Возможно, кто-то, кто читает элементы git-bash, знает, что это за проблема с CreateProcess.

@MadScientist Обновлено с выдержками из файла Makefile, который вызывает проблемы. Я знаю, что Makefile очень чувствителен к пробелам, но я уверен, что в makefile таких вещей нет. Это просто последний вызов для создания общей библиотеки не работает.

@torek Это оболочка bash, предоставляемая Git, в которой есть библиотека mingw64 с компилятором C++ и утилитой make. Я просто использую его для подготовки общей библиотеки для Linux. Вместо использования компьютера с Linux я хочу создать общую библиотеку и Windows DLL на одном компьютере.

(Возможно, это понятнее: git-bash входит в состав дистрибутива Git-for-Windows, но не имеет ничего общего с самим Git.)

1 Ответ 1

Причина, по которой я предложил проблемы с пробелами в своем комментарии выше, заключается в том, что сообщение об ошибке ЯСНО показывает, что это проблема с пробелами:

В этом пути к sh.exe есть пробел, и первый напечатанный здесь аргумент C:\Program совершенно ясно показывает, что путь был усечен до пробела.

Я думал, что ваш make-файл устанавливает для SHELL какое-то значение, но, похоже, это не так. Все, что я могу предложить, это либо (а) удалить C:\Program Files\Git\usr\bin из вашего %Path% , либо (б) переустановить Git по пути, который не содержит пробелов, чтобы вы не столкнулся с этой проблемой.

В этом разделе описываются некоторые моменты, которые следует учитывать при использовании библиотек в вашей программе.

Обзор программирования библиотеки

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

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

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

Программирование с библиотеками

Модель программирования оболочки Windows описывает, как программа взаимодействует с программными объектами оболочки Windows. Хотя объекты файловой системы, такие как файлы и каталоги, представлены объектами оболочки Windows, не все объекты оболочки Windows представлены файловой системой. Библиотеки, например, являются объектами оболочки Windows, не имеющими эквивалента в файловой системе. Использование объектов оболочки Windows в вашей программе позволяет вашей программе получать доступ ко всем объектам оболочки, а не только к объектам файловой системы.

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

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

Переход из известных папок в библиотеки

До Windows 7 было обычным делом использовать известную папку, например папку «Мои документы», в качестве папки по умолчанию при сохранении или открытии файлов. В Windows 7 следует использовать соответствующую библиотеку, чтобы пользователь мог работать с вашей программой так же, как и с другими программами Windows 7, такими как Проводник Windows.

Если в настоящее время вы используете API оболочки Windows в своей программе, добавить поддержку библиотек несложно. Например, если вы в настоящее время вызываете функцию SHGetKnownFolderItem для получения местоположения папки «Мои документы», вы можете заменить значение KNOWNFOLDERID известной папки «Мои документы» значением KNOWNFOLDERID соответствующей библиотеки.

В следующей таблице показано соотношение между значениями KNOWNFOLDERID известных папок и значением KNOWNFOLDERID соответствующей библиотеки в Windows 7.

Значения KNOWNFOLDERID известной папки Значения KNOWNFOLDERID библиотеки
FOLDERID_Documents FOLDERID_DocumentsLibrary
FOLDERID_Pictures FOLDERID_PicturesLibrary
FOLDERID_Music FOLDERID_MusicLibrary
FOLDERID_RecordedTV FOLDERID_RecordedTVLibrary

Домашняя группа и общие библиотеки

Добавление поддержки библиотек в вашу программу активирует поддержку общих библиотек в домашней группе. Домашняя группа идентифицируется своим значением KNOWNFOLDERID FOLDERID_HomeGroup. Ваша программа может определить частное или общее местоположение пользователя по умолчанию для сохранения, установив значение DEFAULTSAVEFOLDERTYPE в вызове метода IShellLibrary::GetDefaultSaveFolder.

Использование общего диалогового окна файла с библиотеками

Использование диалогового окна общего файла с библиотеками Диалоговое окно общего файла было обновлено для поддержки библиотек в Windows 7. На следующем рисунке показано, как диалоговое окно общего файла отображается для пользователя в Windows 7.

снимок экрана диалоговое окно общего файла, показывающее библиотеки

В Windows 7, если ваша программа в настоящее время отображает обычное диалоговое окно файла и не изменяет шаблон диалогового окна и не перехватывает какие-либо его события, она автоматически отобразит новую версию диалогового окна Windows 7. В частности, при вызове функции диалогового окна общего файла элементы lpfnHook, hInstance, lpTemplatename структуры OPENFILENAME должны иметь значение NULL, а флаги OFN_ENABLEHOOK и OFN_ENABLETEMPLATE должны быть сняты.

В Windows 7 интерфейсы, связанные с IFileDialog, заменяют стандартные функции диалогового окна файлов, которые использовались в более ранних версиях Windows. Более ранние общие функции диалогового окна файла по-прежнему поддерживаются в Windows 7, но они не обеспечивают полного пользовательского интерфейса Windows 7 и не поддерживают библиотеки. Некоторые из новых функций, поддерживаемых интерфейсами, связанными с IFileDialog, включают:

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

Вы должны использовать интерфейсы, связанные с IFileDialog, когда:

  • вам необходимо настроить общее диалоговое окно файла для вашей программы в Windows 7. Это позволит вашей программе работать с библиотеками и поддерживать настройку вашего диалогового окна.
  • вы хотите, чтобы пользователь мог выбирать несколько файлов в общем диалоговом окне файлов. Это гарантирует, что вы получите правильные пути к выбранному объекту, поскольку содержимое библиотеки может храниться в разных папках.

Для получения дополнительной информации об интерфейсах, связанных с IFileDialog, см.:

Включение выбора библиотеки из пользовательского интерфейса

Если ваша программа позволяет пользователю выбирать папку, например, для функций импорта или экспорта в Windows 7, она также должна позволять пользователю выбирать библиотеку.Интерфейс IFileOpenDialog и функция SHBrowseForFolder позволяют пользователю выбрать библиотеку при появлении запроса на выбор папки. Интерфейс IFileOpenDialog предпочтительнее функции SHBrowseForFolder, поскольку IFileOpenDialog поддерживает пользовательский интерфейс Windows 7.

Чтобы разрешить пользователям выбирать папки при использовании интерфейса IFileOpenDialog, вызовите SetOptions с установленным флагом FOS_PICKFOLDERS и убедитесь, что флаг FOS_FORCEFILESYSTEM снят.

Чтобы разрешить пользователям выбирать папки при вызове функции SHBrowseForFolder, в элементе ulFlags структуры BROWSEINFO установите флаг BIF_USENEWUI и снимите флаг BIF_RETURNONLYFSDIRS.

Доступ к содержимому библиотеки в программе

Для доступа к содержимому библиотеки необходимо использовать API оболочки Windows. Функции API файловой системы нельзя использовать для доступа к содержимому библиотеки, поскольку библиотеки не являются объектами файловой системы. Если ваша программа использует пользовательский файловый браузер, основанный на API файловой системы, она не сможет просматривать библиотеки или получать доступ к их содержимому.

В этом разделе описывается, как получить доступ к содержимому библиотеки, чтобы выбрать лучший способ обновления программы для работы с библиотеками.

Доступ к содержимому библиотеки с помощью интерфейса IShellLibrary

Самый простой способ для программы получить доступ к содержимому библиотеки — использовать Shell Library API. Если вы работаете над программой, использующей API файловой системы, API библиотеки оболочки может возвращать папки файловой системы библиотеки, что сводит к минимуму изменения в существующем программном коде.

Доступ к содержимому библиотеки с помощью Shell API

Поскольку объекты библиотеки являются частью модели программирования оболочки, их можно использовать с другими API-интерфейсами оболочки Windows. Например, вы можете использовать интерфейсы IShellItem и IShellFolder в своей программе вместе с соответствующими вспомогательными функциями для доступа к содержимому библиотеки таким же образом, как если бы вы перечисляли папки и содержимое папок для доступа к содержимому с помощью API-интерфейсов файловой системы.

API оболочки Windows поддерживают два режима перечисления для доступа к содержимому библиотеки:

Просмотреть перечисление

Перечисление просмотра — это режим перечисления по умолчанию, в котором перечисляется содержимое папки библиотеки. Снимите флаг SHCONTF_NAVIGATION_ENUM, чтобы использовать этот режим.

Перечисление навигации

Перечисление навигации перечисляет папки библиотеки. Установите флаг SHCONTF_NAVIGATION_ENUM, чтобы использовать этот режим.

Если ваша программа использует настраиваемый элемент управления деревом для навигации по папкам пользователя, перечисление папок в режиме перечисления навигации даст вам список папок библиотеки, соответствующий тому, как Проводник Windows перечисляет папки в Windows 7.

Примеры использования этих функций в программе см. в образце ShellStorage в Windows SDK.

Сохранение пользовательского контента в библиотеке

Ваша программа может сохранять пользовательский контент в библиотеку, а также в папку в библиотеке. Точно так же пользователь может сохранить в определенную папку в библиотеке или просто сохранить в библиотеке.

В каждой библиотеке есть папка, которая назначается местом сохранения по умолчанию. Место сохранения по умолчанию определяется при создании библиотеки; однако пользователь может изменить место сохранения по умолчанию на любую папку в библиотеке. Хотя пользователю не нужно настраивать место сохранения по умолчанию, у него есть возможность изменить его. Если пользователь удалит папку, которая в данный момент установлена ​​в качестве места сохранения по умолчанию, библиотека автоматически настроит следующую папку в библиотеке в качестве места сохранения по умолчанию.

Существует несколько способов сохранения пользовательского контента в библиотеке.

API оболочки

Если вы используете модель программирования оболочки и сохраняете элемент оболочки, представленный IShellItem, IStorage или IStream, в библиотечный объект, элемент оболочки будет автоматически сохранен в месте сохранения по умолчанию в библиотеке.< /p>

API файловой системы

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

Примеры использования этих функций в программе см. в образце ShellStorage в Windows SDK.

Поддержка операций перетаскивания в библиотеке

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

Примеры того, как добавить поддержку библиотек для функций перетаскивания ваших программ, см. в образце ShellLibraryCommandLine в Windows SDK.

Синхронизация с библиотекой

В этом разделе описывается, как программа может обновлять представление содержимого библиотеки.

Массовое обновление

Поскольку пользователь может изменять папки библиотеки в интерактивном режиме, когда ваша программа не запущена, ваша программа должна вызывать SHResolveLibrary, когда она начинает обнаруживать и сохранять любые изменения в библиотеке. Shell API предоставляет функцию SHResolveLibrary, позволяющую программе получать текущее содержимое библиотеки и текущее расположение любых папок, которые могут содержаться в библиотеке.

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

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

Уведомление Shell API

API оболочки Windows предоставляет функцию SCHhangeNotifyRegister, которая является предпочтительным способом уведомления неслужебных процессов об изменении в библиотеке.

Чтобы обнаруживать изменения элементов в библиотеке с помощью API оболочки Windows, вызовите SHhangeNotifyRegister, чтобы зарегистрировать вашу программу для получения уведомлений об изменениях элементов в папке библиотеки. Эта функция может уведомить вашу программу, если есть изменения в какой-либо библиотеке или только в определенной библиотеке. Уведомления отправляются немедленно при изменении библиотеки.

Уведомление API файловой системы

Уведомления файловой системы должны использоваться в сервисных процессах.

Чтобы обнаружить изменения элементов в библиотеке с помощью API файловой системы, перечислите папки в библиотеке и вызовите FindFirstChangeNotification для каждой папки, которую нужно отслеживать. Ваша программа получит уведомление, когда отслеживаемая папка изменится. Чтобы найти конкретный файл файлов, которые были изменены в папке, вызовите ReadDirectoryChangesW. Чтобы обнаружить изменения в файле описания библиотеки, отслеживайте папку, в которой он находится. Файл описания библиотеки находится в папке FOLDERID_Libraries. Однако файл описания библиотеки не следует открывать или изменять.

Иногда, когда вы пытаетесь установить программу или пакет из исходного кода, вы можете получить сообщение об ошибке следующего вида:

"ошибка при загрузке общих библиотек: невозможно открыть общий объектный файл Нет такого файла или каталога"

Как правило, если имя общей библиотеки пакета — lib, ошибка иногда показывает следующее:

" ошибка при загрузке разделяемых библиотек: lib.so.X: невозможно открыть общий объектный файл: нет такого файла или каталога"

Где X — число.

Эти динамически создаваемые общие библиотеки, необходимые для исполняемых файлов, хранятся в каталогах /lib или /usr/lib.

Приведенная ниже команда может помочь найти библиотеки, необходимые для данного исполняемого файла:

В качестве быстрого обходного пути вы можете попытаться устранить проблему, выполнив команду ldconfig ниже:

sudo ldconfig -v

Теперь во время выполнения системе потребуется найти соответствующий файл библиотеки «.so», поскольку пакет или программа связаны с общей версией библиотеки.

Чтобы найти библиотеку, вызовите команду ниже:

sudo find / -name lib_file.so.x

или вы можете использовать команду apt search. Запишите путь, по которому находится lib_file.so.x, path_to_so_file.

Чтобы включить папку, в которой установлена ​​библиотека, необходимо указать переменную оболочки LD_LIBRARY_PATH.

Если LD_LIBRARY_PATH не определен (запустите echo $LD_LIBRARY_PATH, чтобы узнать), вы можете установить его с помощью команды (в оболочке Bash):

Теперь, используя путь файла .so, который вы нашли выше, path_to_so_file, выполните следующие команды:

экспортировать LD_LIBRARY_PATH $ ./ваш_пакет

Подробнее об общих библиотеках можно узнать здесь.

Если вам нравится контент, мы будем признательны за вашу поддержку, купив нам кофе. Большое спасибо за ваш визит и поддержку.

Николаус Остерхоф

Николаус имеет степень в области разработки программного обеспечения. Увлечен гаджетами с экраном, ностальгирует по телефонам, геймер на пенсии и программист с открытым исходным кодом. Он также любит писать о macOS и Windows. создавайте веб-страницы и отлаживайте длинные программы!

Вам также может понравиться

 Тюнинг Windows: Отключение ненужных служб

Настройка Windows: отключение ненужных служб

Лучшие бесплатные видеоредакторы для Windows

2 сентября 2021 г.

Лучшие бесплатные видеоредакторы для Windows

Читайте также: