Мне кажется, что решением является , а не , чтобы использовать DATA при экспорте данных из основной DLL (DLL, в которой хранятся данные).
Чтобы воспроизвести то, что я имею в виду, вы можете создать проект, имеющий DllDataForward.c:
#include <Windows.h>
EXTERN_C __declspec(dllexport) int myData = 5;
#ifndef _DEBUG
EXTERN_C BOOL WINAPI _DllMainCRTStartup (HINSTANCE hinstDLL, DWORD fdwReason,
LPVOID lpvReserved)
#else
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
#endif
{
if (fdwReason == DLL_PROCESS_ATTACH)
DisableThreadLibraryCalls(hinstDLL);
return TRUE;
UNREFERENCED_PARAMETER (lpvReserved);
}
EXTERN_C __declspec(dllexport) BOOL WINAPI MyFunc()
{
return TRUE;
}
и DllDataForward.def:
LIBRARY "DllDataForward"
EXPORTS
myData
MyFunc
Как правило, вместо «myData» будет использоваться «myData DATA».
Затем вы можете создать ForwardingDll.c:
#include <Windows.h>
#ifndef _DEBUG
EXTERN_C BOOL WINAPI _DllMainCRTStartup (HINSTANCE hinstDLL, DWORD fdwReason,
LPVOID lpvReserved)
#else
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
#endif
{
if (fdwReason == DLL_PROCESS_ATTACH)
DisableThreadLibraryCalls(hinstDLL);
return TRUE;
UNREFERENCED_PARAMETER (lpvReserved);
}
с ForwardingDll.def:
LIBRARY "ForwardingDll"
EXPORTS
myNewData=DllDataForward.myData DATA
MyNewFunc=DllDataForward.MyFunc
Вы должны включить библиотеку импорта DllDataForward.lib, созданную во время компиляции DllDataForward, в качестве входных данных для компоновщика при сборке ForwardingDll.dll. Такая библиотека импорта может быть успешно использована, и вы получите ForwardingDll.dll.
dumpbin.exe ForwardingDll.dll /EXPORTS
производить в качестве выхода
...
ordinal hint RVA name
1 0 MyNewFunc (forwarded to DllDataForward.MyFunc)
2 1 myNewData (forwarded to DllDataForward.myData)
...
Простая тестовая сборка приложения с использованием DllDataForward.lib только с исходным кодом test.c:
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
EXTERN_C __declspec(dllimport) int myNewData;
EXTERN_C __declspec(dllimport) BOOL WINAPI MyNewFunc();
int main()
{
BOOL isSuccess = MyNewFunc();
int i=myNewData;
_tprintf (TEXT("i=%d\nisSuccess=%s\n"),
i, isSuccess? TEXT("TRUE"): TEXT("FALSE"));
}
производить в качестве выхода
i=5
isSuccess=TRUE
ОБНОВЛЕНО : я хочу добавить немного больше информации , почему использование "myData DATA" вместо "myData" в файле DEF помогает, и как использовать трюк, который я предлагаю с существующей DLL , такой как python32.dll без каких-либо изменений в python32.dll и без перекомпиляции . Я покажу, что исходный файл python32.lib пропускает экспорт всех переменных данных, таких как PyBaseObject_Type
. Я покажу, как вы можете создать дополнительный python32.lib , в котором есть символы с данными, которые нам нужны.
Прежде всего я хочу отменить изменения, которые мы вносим в библиотеку импорта после перехода с «myData DATA» на «myData» в файле DEF. Сначала давайте скомпилируем DllDataForward.dll с файлом DEF, имеющим «myData DATA», и посмотрим внутрь библиотеки импорта DllDataForward.LIB:
dumpbin.exe DllDataForward.lib /all >%TEMP%\DllDataForward-lib.txt
notepad %TEMP%\DllDataForward-lib.txt
Мы увидим, что библиотека содержит 6 открытых символов:
224 __IMPORT_DESCRIPTOR_DllDataForward
46A __NULL_IMPORT_DESCRIPTOR
5A8 DllDataForward_NULL_THUNK_DATA
776 __imp__myData
708 _MyFunc@0
708 __imp__MyFunc@0
Затем измените файл DEF с «myData DATA» на «myData», создайте dll и библиотеку импорта и загляните внутрь нее еще раз. Мы увидим, что теперь библиотека импорта имеет 7 (!!!) вместо 6 открытых символов:
23A __IMPORT_DESCRIPTOR_DllDataForward
480 __NULL_IMPORT_DESCRIPTOR
5BE DllDataForward_NULL_THUNK_DATA
78C __imp__myData
78C _myData
71E _MyFunc@0
71E __imp__MyFunc@0
Таким образом, у нас возникла проблема с использованием файла DEF с «myData DATA», поскольку созданная библиотека импорта не содержит общедоступного символа _myData
.
Мы можем остаться с правильной DLL, имеющей «myData DATA», и создать дополнительную вторую библиотеку импорта , которая экспортирует _myData
вручную. Мы не будем вносить никаких изменений в файл DllDataForward.dll, просто сделайте дополнительную библиотеку вручную.
Для этого мы выгружаем экспорт файла DllDataForward.dll с отношением dumpbin.exe DllDataForward.dll /exports
. Мы увидим:
...
ordinal hint RVA name
1 0 00001020 MyFunc = _MyFunc@0
2 1 00003000 myData = _myData
...
Теперь мы создаем новый файл DllDataForward.def в другом каталоге , основываясь только на выводе из dumpbin.exe DllDataForward.dll /exports
:
LIBRARY "DllDataForward"
EXPORTS
myData = _myData
Далее с помощью команды
lib.exe /DEF:DllDataForward.def /OUT:DllDataForward.lib /MACHINE:X86
мы создаем второе DllDataForward.lib
(в другом каталоге оригинал DllDataForward.lib
). Теперь мы можем скомпилировать ForwardingDll.dll , используя два DllDataForward.lib
и получить DLL, которая нам нужна. Test.exe покажет, что подход работает.
Точно так же мы рассматриваем python32.lib из текущей версии 3.2a3:
dumpbin.exe "C:\Program Files\Python32\libs\python32.lib" /all >python32-lib.txt
notepad python32-lib.txt
выясним следующие строки (примерно в начале файла)
1957 public symbols
…
1BCCC _PyArg_Parse
1BCCC __imp__PyArg_Parse
…
1BFF6 __imp__PyBaseObject_Type
…
Мы также можем проверить с помощью
dumpbin C:\Windows\system32\python32.dll /exports >%TEMP%\python32-exports.txt
notepad %TEMP%\python32-exports.txt
что символ PyBaseObject_Type
будет экспортирован как
14 D 001DD5D0 PyBaseObject_Type
Таким образом, мы можем создать дополнительный файл python32.lib из файла python32.def
LIBRARY "python32"
EXPORTS
PyBaseObject_Type
с помощью
lib /DEF:python32.def /OUT:python32.lib /MACHINE:X86
Теперь вы можете определить DEF вашей DLL
LIBRARY "python3"
EXPORTS
PyArg_Parse=python32.PyArg_Parse
PyArg_ParseTuple=python32.PyArg_ParseTuple
PyArg_ParseTupleAndKeywords=python32.PyArg_ParseTupleAndKeywords
PyBaseObject_Type=python32.PyBaseObject_Type DATA
точно так же, как вы изначально хотели, но мы будем использовать обоих"C: \ Program Files \ Python32 \ libs \ python32.lib" и маленький второй python32.lib, который мы создали во время компоновки.
Я сам не использую python и не знаю размер PyBaseObject_Type
, но если я объявлю его как int
EXTERN_C __declspec(dllimport) int PyBaseObject_Type;
Я могу убедиться, что первая часть PyBaseObject_Type
равна 1. Это работает!
Извините за длинный ответ и спасибо всем, кто прочитал весь мой ответ до этого места.