Шаг 1. У меня есть импорт файла lib (main.lib) для моего исполняемого файла (main.exe) который экспортирует некоторые символы. Эти символы экспортируются с использованием extern «C».
Шаг 2. У меня тоже есть исходный файл (extra.cpp) который экспортирует некоторые дополнительные функции. Я генерирую статическую библиотеку ссылок (extra.lib) из него и включаю main.lib в него, так как эти дополнительные функции являются пользователями экспорта из main.exe.
Шаг 3. Длл (bbb.dll) встроено связывание с этой библиотекой (extra.lib) для вызова этих дополнительных функций из main.exe.
(Обратите внимание, что bbb.dll загружается и используется main.exe На первом месте.)
Теперь я пытаюсь повторить шаги 2 и 3, используя Mingw (gcc) вместо MS Visual Studio (cl). Давайте назовем это Шаг 2x и 3x.
Поскольку main.exe — это большой проект с большим количеством файлов … здание libmain.a из источников не хороший вариант, я нашел Вот тот main.lib можно преобразовать в файл .a с помощью следующих команд:
reimp -d main.lib
dlltool -k -d main.def -l libmain.a
# reimp creates the .def file.
# dlltool uses the .def to create the .a that is linked in to the app.
Шаг 2х.
gcc -c -o extra.o -O1 -s -x c++ extra.cpp
ar rs libextra.a extra.o
ar rs libextra.a libmain.a
Шаг 3х.
g++ -O2 -o bbb.dll -shared -x c++ bbb.cpp -static-libgcc -static-libstdc++ -Wl,-s -Wl,--kill-at,--export-all-symbols,--enable-stdcall-fixup -Wl,--large-address-aware -lextra
Я получаю ошибки компоновщика на шаге 3x.
libmain.a(lextra.o):extra.cpp:(.text+0x38): undefined reference to `A_Function_In_main'
Это проблема искажения имени?
Или вообще возможно построить bbb.dll используя gcc таким образом?
Что я делаю не так?
Я использую Visual Studio 2012 на Windows 7. MinGW с gcc 4.6.1.
Проверка, находится ли A_Function_In_main в libmain.a:
nm libmain.a > libmain_dump.txt
Блок текста в libmain_dump.txt относительно ‘A_Function_In_main’
dshms00350.o:
00000000 b .bss
00000000 d .data
00000000 i .idata$4
00000000 i .idata$5
00000000 i .idata$6
00000000 i .idata$7
00000000 t .text
00000000 T A_Function_In_main
00000000 I __imp_A_Function_In_main
U _head_libmain_a
Есть ли способ упростить этот вопрос?
Хотя кажется, что между большой основной программой и дополнительной DLL существует некоторая циклическая зависимость, я предполагаю, что вы просто используете функцию обратного вызова в main. Моим усилиям мешает отсутствие исходного кода или тех же версий MSVC и gcc, которые вы используете. (У меня MS Visual Studio 2010 и mingw gcc-4.7.2) Но суть проблемы, похоже, заключается в преобразовании сгенерированной MS библиотеки импорта для работы с gcc.
В качестве альтернативы вы можете реализовать собственную библиотеку импорта, вызвав LoadLibrary («bbb.dll»), а затем использовать GetProcAddress («A_Function_In_Main»). Но я предполагаю, что ваш реальный проект делает этот подход слишком дорогим.
В качестве диагностики протестируйте библиотеку импорта reimp с помощью более простого тестового стенда:
foo.h
#ifdef FOO_DLL_EXPORTS
#define FOO_DLL_API __declspec(dllexport)
#else
#define FOO_DLL_API __declspec(dllimport)
#endif
extern "C" int FOO_DLL_API foo (int x);
foo.cpp
// define FOO_DLL_EXPORTS when building foo.cpp
#include "foo.h"#include <iostream>
using std::cout;
using std::endl;
extern "C" int FOO_DLL_API foo (int x)
{
return x + 1;
}
int main()
{
cout << "foo.exe foo(1) returns " << foo(1) << endl; // expect 2
return 0;
}
test.cpp
#include "foo.h"#include <iostream>
using std::cout;
using std::endl;
int main()
{
cout << "test.exe foo(3) returns " << foo(3) << endl; // expect 4
return 0;
}
Используйте MSVC для компиляции foo.cpp в foo.exe и импорта библиотеки foo.lib.
# compile foo.cpp; define FOO_DLL_EXPORTS
/ZI /nologo /W3 /WX- /Od /Oy- /D "FOO_DLL_EXPORTS" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fp"Debug\foo.pch" /Fa"Debug\" /Fo"Debug\" /Fd"Debug\vc100.pdb" /Gd /analyze- /errorReport:queue
# linker; generate foo.lib
/OUT:"C:\svn_local\0\Users\mku\MinGW_w32\stackoverflow.com\20484904\trunk\msvc2010_build_foo_exe\foo\Debug\foo.exe" /INCREMENTAL /NOLOGO "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MANIFEST /ManifestFile:"Debug\foo.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"C:\svn_local\0\Users\mku\MinGW_w32\stackoverflow.com\20484904\trunk\msvc2010_build_foo_exe\foo\Debug\foo.pdb" /SUBSYSTEM:CONSOLE /PGD:"C:\svn_local\0\Users\mku\MinGW_w32\stackoverflow.com\20484904\trunk\msvc2010_build_foo_exe\foo\Debug\foo.pgd" /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"foo.lib" /MACHINE:X86 /ERRORREPORT:QUEUE
Убедитесь, что нет ошибок компиляции / ссылки.
Убедитесь, что код возврата foo.exe равен 2, как и ожидалось.
Используйте mingw-utils reimp для преобразования foo.lib в libfoo.a для использования с gcc. (Предполагая, что реальный foo.cpp нецелесообразно перестраивать, хотя в этом небольшом примере foo.cpp можно перестроить с помощью gcc-4.7.2)
reimp -d foo.lib
# reimp creates the foo.def file.
dlltool -k -d foo.def -l libfoo.a
# dlltool uses the .def to create the .a that is linked in to the app.
Убедитесь, что libfoo.a содержит __imp_foo.
nm libfoo.a | grep __imp_foo
00000000 I __imp__foo
Используйте gcc для компиляции test.cpp для test.exe с библиотекой импорта libfoo.a.
g++.exe test.o -o test.exe -static -static-libgcc -static-libstdc++ -L"C:/MinGW/lib" /MinGW/lib/gcc/mingw32/4.7.2/libstdc++.a /MinGW/lib/gcc/mingw32/4.7.2/libgcc.a libfoo.a
Убедитесь, что нет ошибок компиляции / ссылки.
Убедитесь, что код возврата test.exe равен 4, как и ожидалось.
Это работает в моей системе.
Microsoft Visual Studio 2010 Версия 10.0.40219.1 SP1Rel.
gcc 4.7.2
переоснащать источники из http://sourceforge.net/p/mingw/utils/ci/master/tree/reimp/
Других решений пока нет …