extern "C" void __declspec(dllexport) do_something()
{
//...
};
Управление сборкой таблицы импорта вызовов (раннее связывание)
Суть задачи сводится к перенаправлению связей между точками вызова функций(*.exe) и точками их реализаций (*.dll), с сохранением совместимости библиотеки на уровне бинарного кода, и исполнимого файла на уровне исходников.
Пробовал механизм сборки архивов (*.а), с использованием *.def файлов, что, вероятно, позволяет управлять соответствием имен функций в *.exe и *.dll, для решения проблемы разности манглинга(mangling) имен, но не вышло.
Скажем, не получилось желанное чудо. Если удается собрать архив с желанным экспортом, и исполнимый скомпоновать, то, как и следовало предположить, при запуске точка входа не находится, т.к. в таблице импорта у исполнимого ничего не изменилось,. Т.е. промежуточное звено (архив - *.a) дает компоновщику основание считать, что необходимая функция есть в библиотеке, а не переадресовывает её, как ожидалось.
Как-то так:
-Библиотека экспортирует функцию "_do_something":
// userlib.cpp:
Код:
-Исполнимый импортирует функцию "_do_some".
// main.cpp:
Код:
extern "C" void __declspec(dllimport) do_some();
//...
do_some();
//...
//...
do_some();
//...
//userlib.def:
Код:
EXPORTS
do_something = do_some // _do_something = _do_some
do_something = do_some // _do_something = _do_some
//makefile
Код:
CXX = g++ -c
LINK = g++ -s -static-libgcc
DLLTOOL = dlltool
REMOVE = erase /F
TARGET = executive.exe
LIBS = -L.\ -luserlib
LIBRARY = userlib.dll
all: $(LIBRARY) $(TARGET)
$(LIBRARY): userlib.o
$(LINK) -shared -o $@ $^
$(DLLTOOL) --input-def userlib.def --dllname $(LIBRARY) --output-lib libuserlib.a
userlib.o: userlib.cpp
$(CXX) -o $@ $^
$(TARGET): main.o
$(LINK) $(LIBS) -o $@ $^ libuserlib.a
main.o: main.cpp
$(CXX) -o $@ $^
clean:
$(REMOVE) $(TARGET) $(LIBRARY) libuserlib.a userlib.o main.o
LINK = g++ -s -static-libgcc
DLLTOOL = dlltool
REMOVE = erase /F
TARGET = executive.exe
LIBS = -L.\ -luserlib
LIBRARY = userlib.dll
all: $(LIBRARY) $(TARGET)
$(LIBRARY): userlib.o
$(LINK) -shared -o $@ $^
$(DLLTOOL) --input-def userlib.def --dllname $(LIBRARY) --output-lib libuserlib.a
userlib.o: userlib.cpp
$(CXX) -o $@ $^
$(TARGET): main.o
$(LINK) $(LIBS) -o $@ $^ libuserlib.a
main.o: main.cpp
$(CXX) -o $@ $^
clean:
$(REMOVE) $(TARGET) $(LIBRARY) libuserlib.a userlib.o main.o
Для упрощения опущены некоторые детали, но если хочется/нужно, могу выложить весь "проект" :)
Вообщем тут детально описывать не буду, скажу только вот, что:
// main.def:
Код:
IMPORTS
do_some = lib.dll.do_something
do_some = lib.dll.do_something
// makefile
Код:
...
...
$(TARGET): main.o main.def
$(LINK) $(INCLUDE) $(LIBS) -o $@ $^
...
$(TARGET): main.o main.def
$(LINK) $(INCLUDE) $(LIBS) -o $@ $^
Весь недо-"проект" во вложении.
И вот еще ссылка - binutils. Может кто-то сочтёт полезной.