Вот MWE, демонстрирующий проблему (я включил полный CMake для удобства воспроизведения, но я не думаю, что там есть что-то актуальное). Если я удалю функцию power_six из библиотеки и перестану пытаться ее вызвать, все будет работать как положено, но если определение существует в библиотеке, то основной исполняемый файл выйдет из строя при загрузке библиотеки. Может ли кто-нибудь объяснить, что я делаю неправильно и как в этом случае должно работать разрешение символов? В документации Windows я нашел хорошие ресурсы по разрешению путей к библиотекам, а спецификация PE указывает на то, как хранится связь, но я не вижу никакой информации о правилах разрешения символов в этом случае. Ожидается ли, что DllMain будет реализован таким образом, чтобы каким-то образом заполнять символы? Если да, то как это сделать?
Код: Выделить всё
// lib\lib.h
int square(int x);
int power_six(int x);
Код: Выделить всё
// lib\lib.c
#include "lib.h"
#include "windows.h"
// This must be provided by another file in the process space.
int cube(int x);
int square(int x) {
return x * x;
}
int power_six(int x) {
return cube(square(x));
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
// No-op included because the FORCE docs indicate that the entry point must
// be defined for this flag to have an effect.
}
Код: Выделить всё
# lib\CMakeLists.txt
cmake_minimum_required(VERSION 3.26.4 FATAL_ERROR)
project(lib VERSION 0.0.1 LANGUAGES C)
# For simplicity in testing, always export symbols on Windows
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
add_library(lib SHARED lib.c)
target_include_directories(lib PUBLIC "$" "$")
target_link_options(lib PRIVATE "/FORCE:UNRESOLVED")
include(GNUInstallDirs)
install(
TARGETS lib
DESTINATION ${CMAKE_INSTALL_LIBDIR}
EXPORT ${PROJECT_NAME}-exports
)
install(
FILES lib.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
include(CMakePackageConfigHelpers)
foreach(tree_type BUILD INSTALL)
if(tree_type STREQUAL "BUILD")
set(install_location ".")
else()
set(install_location "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
endif()
set(build_location "${PROJECT_BINARY_DIR}/${install_location}")
write_basic_package_version_file(
"${build_location}/${PROJECT_NAME}-config-version.cmake"
VERSION ${CMAKE_PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion)
configure_package_config_file("${CMAKE_CURRENT_LIST_DIR}/cmake/config.cmake.in"
"${build_location}/${PROJECT_NAME}-config.cmake"
INSTALL_DESTINATION "${install_location}")
if(tree_type STREQUAL "BUILD")
export(EXPORT ${PROJECT_NAME}-exports
FILE "${PROJECT_NAME}-targets.cmake"
NAMESPACE ${PROJECT_NAME}::)
else()
install(DIRECTORY "${build_location}/" DESTINATION "${install_location}")
install(EXPORT ${PROJECT_NAME}-exports
DESTINATION "${install_location}"
FILE "${PROJECT_NAME}-targets.cmake"
NAMESPACE ${PROJECT_NAME}::)
endif()
endforeach()
Код: Выделить всё
// lib\cmake\config.cmake.in
@PACKAGE_INIT@
cmake_minimum_required(VERSION @CMAKE_MINIMUM_REQUIRED_VERSION@)
include("${CMAKE_CURRENT_LIST_DIR}/lib-targets.cmake" REQUIRED)
include("${CMAKE_CURRENT_LIST_DIR}/lib-config-version.cmake" REQUIRED)
set(${CMAKE_FIND_PACKAGE_NAME}_CONFIG "${CMAKE_CURRENT_LIST_FILE}")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(${CMAKE_FIND_PACKAGE_NAME} CONFIG_MODE)
Код: Выделить всё
# executable\main.c
#include
#include "windows.h"
// Here's the definition of cube that should be visible to lib.c
int cube(int x) {
return x * x * x;
}
// Option 1: Load-time linkage
/*#include "lib.h"*/
/*int main() {*/
/* int const x = 2;*/
/* int const x_2 = square(x);*/
/* printf("The square of %d is %d\n", x, x_2);*/
/* int const x_6 = power_six(x);*/
/* printf("The sixth power of %d is %d\n", x, x_2);*/
/*}*/
// Option 2: Run-time dynamic linking
typedef int (__cdecl *MYPROC)(int);
int main() {
int const x = 2;
int x_2 = -1;
int x_6 = -1;
char const * path_to_lib = ...;
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult = FALSE;
printf("Attempting to load the library\n");
hinstLib = LoadLibrary(path_to_lib);
if (hinstLib != NULL)
{
printf("Found the lib\n");
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "square");
if (NULL != ProcAdd)
{
printf("Found the function\n");
x_2 = (ProcAdd) (x);
}
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "power_six");
if (NULL != ProcAdd)
{
printf("Found the function\n");
x_6 = (ProcAdd) (x);
}
fFreeResult = FreeLibrary(hinstLib);
}
printf("The square of %d is %d\n", x, x_2);
}
Код: Выделить всё
// executable\CMakeLists.txt
cmake_minimum_required(VERSION 3.26.4 FATAL_ERROR)
project(example VERSION 0.0.1 LANGUAGES C)
add_executable(example main.c)
find_package(lib)
target_link_libraries(example PRIVATE lib::lib)
include(GNUInstallDirs)
install(
TARGETS example
DESTINATION bin
EXPORT ${PROJECT_NAME}-exports
)
Я спросил об этом на форуме разработчиков Microsoft, и пришел к выводу, что это невозможно.
Подробнее здесь: https://stackoverflow.com/questions/790 ... on-windows
Мобильная версия