Я использую Linux (в частности, Ubuntu 20.04) и хотел бы знать, есть ли способ создать динамическую библиотеку, которую можно было бы связать с машиной Windows. Я использую GNU make
и кросс-компилятор mingw
, чтобы попытаться сделать это.
Вот простой make-файл, который я сделал для тестирования:
CXX := x86_64-w64-mingw32-g++
CXX_FLAGS := -static-libgcc -static-libstdc++
main.exe: example.dll test_exe.o
$(CXX) $(CXX_FLAGS) -o main.exe test_exe.o -L. -lexample
example.dll: example.o
$(CXX) $(CXX_FLAGS) -shared -o example.dll example.o -Wl,--out-implib,libexample.a
%.o: %.cpp
$(CXX) -c -fPIC $<
Для справки: у меня есть файл example.hpp
, в котором объявлены методы, которые я хочу включить в библиотеку, и эти методы определены в example.cpp
. test_exe.cpp
содержит мою функцию main
и вызывает методы, определенные в библиотеке. Запуск make
генерирует (я полагаю) объектные файлы example.o
и test_exe.o
, за которыми следует динамически связанная библиотека с именем example.dll
и соответствующая ей библиотека импорта с именем libexample.a
, а затем связывает все вместе в исполняемый файл с именем main.exe
. Созданный вывод, похоже, делает это, но у меня нет возможности полностью проверить, действительно ли выходные файлы являются тем, что я ожидаю.
Кроме того, я установил CXX_FLAGS
для статической связи стандартных библиотек c
и c++
, потому что, если я этого не сделаю, я получаю сообщение об ошибке The application was unable to start correctly (0xc000007b)
. Я предполагаю, что это связано с тем, что по умолчанию файлы ожидают версию стандартных библиотек для Linux (которую нельзя найти на компьютере с Windows), и явное связывание переопределяет этот параметр? Google говорит, что эта ошибка может указывать на то, что у меня неправильная версия приложения для моей машины, поэтому в этом есть смысл.
Отраженные команды, когда я запускаю make
:
x86_64-w64-mingw32-g++ -c -fPIC example.cpp
x86_64-w64-mingw32-g++ -static-libgcc -static-libstdc++ -shared -o example.dll example.o -Wl,--out-implib,libexample.a
x86_64-w64-mingw32-g++ -c -fPIC test_exe.cpp
x86_64-w64-mingw32-g++ -static-libgcc -static-libstdc++ -o main.exe test_exe.o -L. -lexample
Когда я связываюсь в Linux, все работает в основном так, как ожидалось. Исполняемый файл работает в Windows, пока .dll
находится в текущем каталоге, и выдает ошибку при его удалении.
Во-первых, я не ожидал, что исполняемый файл будет работать независимо от того, присутствует ли библиотека импорта libmath.a
. Я предполагал, что связываюсь с библиотекой импорта, которая косвенно обертывает динамическую библиотеку, но, похоже, это не так. Кто-нибудь знает, что на самом деле происходит, и почему я не связываюсь с библиотекой импорта?
Мой другой вопрос требует немного больше пояснений. В идеале я хотел бы иметь возможность создать динамическую библиотеку в Linux, отправить ее на компьютер с Windows и связать там с произвольным исполняемым файлом. Я не совсем уверен, возможно ли это, потому что Windows должна указывать __declspec(dllexport)
, а Linux — нет, но хотелось бы знать, так ли это. Я попытался переместить свои динамические библиотеки и библиотеки импорта (example.dll
и libexample.a
) вместе с заголовочным файлом моей библиотеки (example.hpp
) в каталог с новым файлом (testapp.cpp
), указывающим альтернативный метод main
.
На компьютере с Windows я запускаю g++ -c testapp.cpp
, чтобы создать объектный файл, а затем пытаюсь связать его. Когда я запускаю g++ -o app.exe testapp.o -L. -lexample
, чтобы попытаться сгенерировать исполняемый файл, связанный с динамической библиотекой (через библиотеку импорта), я получаю следующую ошибку: undefined reference to 'square(int)'
. square(int)
— это функция, определенная в библиотеке, возвращающая квадрат целого числа. Я также попытался пометить функцию в моем заголовочном файле как __declspec(dllimport)
, что изменило сообщение об ошибке на: undefined reference to '_imp___Z6squarei'
. Возможно ли в Windows связать .dll, которая изначально не указывала __declspec(dllexport)
для своих функций (т. е. разработанная в Linux)?
Сборка ОС: Ubuntu 20.04 - версия 9.3.0 g++
Целевая ОС: Windows 10 (проверено в виртуальной машине) - версия 9.2.0 g++
Та же ошибка. Спасибо за предложение!
Это странно, ты можешь бегать nm -C libexample.a
и nm -CD example.dll
?
Я получаю разные результаты в зависимости от того, в какой ОС я запускаю эти команды. В Windows первая выводит серию строк, например nm: d0000xx.o: file format not recognized
, а вторая говорит nm: example.dll: file format not recognized
. В linux выводит ряд одинаковых nm: d0000xx.o
, но за ними следует то, что, как я предполагаю, является информацией, описывающей каждый идентификатор. Странно, второй мне говорит nm: example.dll: no symbols
.
В конце концов я понял. Команда, которая сработала, была: g++ -o alt.exe testapp.o libexample.a
. Я не совсем уверен, почему это работает, когда то, что я пробовал раньше, не работало, но теперь оно работает так, как ожидалось.
Что интересно, он все равно работает, даже если я нигде не указываю __declspec(dllimport)
. Я также не уверен, почему это работает, но я думаю, что я все еще использую компилятор GNU, а не компилятор Windows по умолчанию.
Попробуйте связать конкретно с библиотекой импорта, т.е. укажите
libexample.a
, а не-lexample
.