Действительно ли безопасно вызвать dll функцию от нескольких потоков в отдельном приложении?

При условии, что в описанном проекте только заголовочные файлы в каталоге mylib/include должны считаться общедоступными:

Верхний уровень CMakeLists.txt для mylib должен содержать:

[110 ]

Это гарантирует, что проекты, включающие mylib, будут иметь доступ только к файлам в каталоге include/. Файлы в include/ могут использоваться как #include , а файлы в include/mylib (общее соглашение) могут использоваться как #include .

Верхний уровень CMakeLists.txt для myapp должен включать:

cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
project(myapp VERSION 0.1 LANGUAGES CXX)

add_subdirectory(libs/mylib)

add_executable(${MyAppName} ${MyApp_SOURCES})
target_link_libraries(${MyAppName} ${MyLibName}

Использование add_subdirectory гарантирует, что mylib будет построено до myapp, а target_link_libraries добавляет [ 1117] к исполняемому файлу.

Как упоминал Цалумэн, обязательно посмотрите учебники по CMake и предпочитаете использовать cmake --build . вместо make.

11
задан Daniel Rikowski 11 April 2009 в 08:08
поделиться

4 ответа

Краткий ответ:

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

Длинный ответ:

Если это , то на самом деле возможно зависит от функций DLL использовать совместно изменяемое состояние или нет.

Например, если вы делаете что-то вроде этого:

DLL_SetUser(UserName, Password)
if DLL_IsAuthenticated then
begin
...
end;

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

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

if DLL_IsAuthenticated(UserName, Password) then
begin
...
end;

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

Резюме:

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

По крайней мере, пока у вас не возникнут проблемы с производительностью.

17
ответ дан 3 December 2019 в 05:59
поделиться

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

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

Обратите внимание, что DLL особенная в том смысле, что вы получать уведомления, когда процесс или поток присоединяется к DLL или отсоединяется от нее. См. Документацию для функции обратного вызова DllMain для объяснения, и этой статьи для примера, как использовать это в написанной на Delphi DLL. Поэтому, если ваши потоки не являются полностью независимыми друг от друга (и нет общих данных, к которым имеется доступ для записи), вам понадобятся некоторые общие структуры данных с синхронизированным доступом. Различные уведомления могут помочь вам с правильной настройкой любых структур данных в вашей DLL.

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

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

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

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

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

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

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

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

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

4
ответ дан 3 December 2019 в 05:59
поделиться

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

0
ответ дан 3 December 2019 в 05:59
поделиться

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

Я не знаком с работой DLL-библиотеки аутентификации Delphi 2009 Возможно, вам следует добавить эту информацию в заголовок (о котором вы говорите конкретно о DLL-библиотеках Delphi 2009)

-1
ответ дан 3 December 2019 в 05:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: