要獲得主程序和dll共享的linux的行爲,您可以從dll或主程序中導出該變量。其他模塊必須導入該變量。
你這樣做,通過使用DEF文件(see microsoft's documentation),或者通過它使用的任何其他模塊(see microsoft's documentation)與__declspec(dllexport)
在那裏的定義,並__declspec(dllimport)
標記與變量的用途。這與任何函數,對象或變量如何在Windows中的模塊之間共享相同。
如果您希望程序在運行時加載庫,但主程序可能必須在加載庫之前使用該變量,那麼程序應該導出該變量,並且該DLL應該導入它。這裏有一點雞雞蛋問題,因爲DLL依賴於主程序,而主程序依賴於DLL。請參閱http://www.lurklurk.org/linkers/linkers.html#wincircular
我已經寫了一個例子,說明如何使用Microsoft的編譯器和mingw(gcc在windows中)來執行此操作,包括程序和庫之間可以鏈接的所有不同方式(靜態,dll加載在程序開始時,DLL在運行時期間加載)
main.h
#ifndef MAIN_H
#define MAIN_H
// something that includes this
// would #include "linkage_importing.h"
// or #include "linkage_exporting.h"
// as appropriate
#ifndef EXPLICIT_MAIN
LINKAGE int x;
#endif // EXPLICIT_MAIN
#endif // MAIN_H
的main.c
#ifdef EXPLICIT_DLL
#include "dyn_link.h"
#endif // EXPLICIT_DLL
#include <stdio.h>
#include "linkage_exporting.h"
#include "main.h"
#include "linkage_importing.h"
#include "dll.h"
FNCALL_DLL get_call_dll(void);
int main(int argc, char* argv[])
{
FNCALL_DLL fncall_dll;
fncall_dll = get_call_dll();
if (fncall_dll)
{
x = 42;
printf("Address of x as seen from main() in main.c: %p\n", &x);
printf("x is set to %i in main()\n", x);
fncall_dll();
// could also be called as (*fncall_dll)();
// if you want to be explicit that fncall_dll is a function pointer
printf("Value of x as seen from main() after call to call_dll(): %i\n", x);
}
return 0;
}
FNCALL_DLL get_call_dll(void)
{
#ifdef EXPLICIT_DLL
return get_ptr("dll.dll", "call_dll");
#else
return call_dll;
#endif // EXPLICIT_DLL
}
DLL。ħ
dll.c
#ifdef EXPLICIT_MAIN
#include "dyn_link.h"
#endif // EXPLICIT_MAIN
#include <stdio.h>
#include "linkage_importing.h"
#include "main.h"
#include "linkage_exporting.h"
#include "dll.h"
int* get_x_ptr(void);
LINKAGE void call_dll(void)
{
int* x_ptr;
x_ptr = get_x_ptr();
if (x_ptr)
{
printf("Address of x as seen from call_dll() in dll.c: %p\n", x_ptr);
printf("Value of x as seen in call_dll: %i()\n", *x_ptr);
*x_ptr = 31415;
printf("x is set to %i in call_dll()\n", *x_ptr);
}
}
int* get_x_ptr(void)
{
#ifdef EXPLICIT_MAIN
return get_ptr("main.exe", "x"); // see note in dyn_link.c about using the main program as a library
#else
return &x;
#endif //EXPLICIT_MAIN
}
dyn_link.h
#ifndef DYN_LINK_H
#define DYN_LINK_H
// even though this function is used by both, we link it
// into both main.exe and dll.dll as necessary.
// It's not shared in a dll, because it helps us load dlls :)
void* get_ptr(const char* library, const char* object);
#endif // DYN_LINK_H
dyn_link.c
#include "dyn_link.h"
#include <windows.h>
#include <stdio.h>
void* get_ptr(const char* library, const char* object)
{
HINSTANCE hdll;
FARPROC ptr;
hdll = 0;
ptr = 0;
hdll = LoadLibrary(library);
// in a better dynamic linking library, there would be a
// function that would call FreeLibrary(hdll) to cleanup
//
// in the case where you want to load an object in the main
// program, you can use
// hdll = GetModuleHandle(NULL);
// because there's no need to call LoadLibrary on the
// executable if you can get its handle by some other means.
if (hdll)
{
printf("Loaded library %s\n", library);
ptr = GetProcAddress(hdll, object);
if (ptr)
{
printf("Found %s in %s\n", object, library);
} else {
printf("Could not find %s in %s\n", object, library);
}
} else {
printf("Could not load library %s\n", library);
}
return ptr;
}
linkage_importing.h
// sets up some macros to handle when to use "__declspec(dllexport)",
// "__declspec(dllimport)", "extern", or nothing.
// when using the LINKAGE macro (or including a header that does):
// use "#include <linkage_importing.h>" to make the LINKAGE macro
// do the right thing for importing (when using functions,
// variables, etc...)
//
// use "#include <linkage_exporting.h>" to make the LINKAGE macro
// do the right thing for exporting (when declaring functions,
// variables, etc).
//
// You can include either file at any time to change the meaning of
// LINKAGE.
// if you declare NO_DLL these macros do not use __declspec(...), only
// "extern" as appropriate
#ifdef LINKAGE
#undef LINKAGE
#endif
#ifdef NO_DLL
#define LINKAGE extern
#else
#define LINKAGE extern __declspec(dllimport)
#endif
linkage_exporting.h
// See linkage_importing.h to learn how this is used
#ifdef LINKAGE
#undef LINKAGE
#endif
#ifdef NO_DLL
#define LINKAGE
#else
#define LINKAGE __declspec(dllexport)
#endif
構建MinGW的明確both.sh
#! /bin/bash
echo Building configuration where both main
echo and dll link explicitly to each other
rm -rf mingw_explicit_both
mkdir -p mingw_explicit_both/obj
cd mingw_explicit_both/obj
# compile the source code (dll created with position independent code)
gcc -c -fPIC -DEXPLICIT_MAIN ../../dll.c
gcc -c -DEXPLICIT_DLL ../../main.c
gcc -c ../../dyn_link.c
#create the dll from its object code the normal way
gcc -shared -odll.dll dll.o dyn_link.o -Wl,--out-implib,libdll.a
# create the executable
gcc -o main.exe main.o dyn_link.o
mv dll.dll ..
mv main.exe ..
cd ..
構建MinGW的明確dll.sh
#! /bin/bash
echo Building configuration where main explicitly
echo links to dll, but dll implicitly links to main
rm -rf mingw_explicit_dll
mkdir -p mingw_explicit_dll/obj
cd mingw_explicit_dll/obj
# compile the source code (dll created with position independent code)
gcc -c -fPIC ../../dll.c
gcc -c -DEXPLICIT_DLL ../../main.c
gcc -c ../../dyn_link.c
# normally when linking a dll, you just use gcc
# to create the dll and its linking library (--out-implib...)
# But, this dll needs to import from main, and main's linking library doesn't exist yet
# so we create the linking library for main.o
# make sure that linking library knows to look for symbols in main.exe (the default would be a.out)
gcc -omain.exe -shared main.o -Wl,--out-implib,main.a #note this reports failure, but it's only a failure to create main.exe, not a failure to create main.a
#create the dll from its object code the normal way (dll needs to know about main's exports)
gcc -shared -odll.dll dll.o dyn_link.o main.a -Wl,--out-implib,libdll.a
# create the executable
gcc -o main.exe main.o dyn_link.o
mv dll.dll ..
mv main.exe ..
cd ..
構建MinGW的明確main.sh
#! /bin/bash
echo Building configuration where dll explicitly
echo links to main, but main implicitly links to dll
rm -rf mingw_explicit_main
mkdir -p mingw_explicit_main/obj
cd mingw_explicit_main/obj
# compile the source code (dll created with position independent code)
gcc -c -fPIC -DEXPLICIT_MAIN ../../dll.c
gcc -c ../../main.c
gcc -c ../../dyn_link.c
# since the dll will link dynamically and explicitly with main, there is no need
# to create a linking library for main, and the dll can be built the regular way
gcc -shared -odll.dll dll.o dyn_link.o -Wl,--out-implib,libdll.a
# create the executable (main still links with dll implicitly)
gcc -o main.exe main.o -L. -ldll
mv dll.dll ..
mv main.exe ..
cd ..
構建MinGW的implicit.sh
#! /bin/bash
echo Building configuration where main and
echo dll implicitly link to each other
rm -rf mingw_implicit
mkdir -p mingw_implicit/obj
cd mingw_implicit/obj
# compile the source code (dll created with position independent code)
gcc -c -fPIC ../../dll.c
gcc -c ../../main.c
# normally when linking a dll, you just use gcc
# to create the dll and its linking library (--out-implib...)
# But, this dll needs to import from main, and main's linking library doesn't exist yet
# so we create the linking library for main.o
# make sure that linking library knows to look for symbols in main.exe (the default would be a.out)
gcc -omain.exe -shared main.o -Wl,--out-implib,main.a #note this reports failure, but it's only a failure to create main.exe, not a failure to create main.a
# create the dll from its object code the normal way (dll needs to know about main's exports)
gcc -shared -odll.dll dll.o main.a -Wl,--out-implib,libdll.a
# create the executable (exe needs to know about dll's exports)
gcc -o main.exe main.o -L. -ldll
mv dll.dll ..
mv main.exe ..
cd ..
構建MinGW的static.sh
#! /bin/bash
echo Building configuration where main and dll
echo statically link to each other
rm -rf mingw_static
mkdir -p mingw_static/obj
cd mingw_static/obj
# compile the source code
gcc -c -DNO_DLL ../../dll.c
gcc -c -DNO_DLL ../../main.c
# create the static library
ar -rcs dll.a dll.o
# link the executable
gcc -o main.exe main.o dll.a
mv main.exe ../
cd ..
構建MSVC明確both.bat
@echo off
echo Building configuration where both main
echo and dll link explicitly to each other
rd /s /q win_explicit_both
md win_explicit_both\obj
cd win_explicit_both\obj
rem compile the source code
cl /nologo /c /DEXPLICIT_MAIN ..\..\dll.c
cl /nologo /c /DEXPLICIT_DLL ..\..\main.c
cl /nologo /c ..\..\dyn_link.c
rem create the dll from its object code the normal way
link /nologo /dll dll.obj dyn_link.obj
rem create the executable
link /nologo main.obj dyn_link.obj
move dll.dll ..\
move main.exe ..\
cd ..
構建MSVC明確dll.bat
@echo off
echo Building configuration where main explicitly
echo links to dll, but dll implicitly links to main
rd /s /q win_explicit_dll
md win_explicit_dll\obj
cd win_explicit_dll\obj
rem compile the source code
cl /nologo /c ..\..\dll.c
cl /nologo /c /DEXPLICIT_DLL ..\..\main.c
cl /nologo /c ..\..\dyn_link.c
rem normally when linking a dll, you just use the link command
rem that creates the dll and its linking library.
rem But, this dll needs to import from main, and main's linking library doesn't exist yet
rem so we create the linking library for main.obj
rem make sure that linking library knows to look for symbols in main.exe (the default would be main.dll)
lib /nologo /def /name:main.exe main.obj
rem create the dll from its object code the normal way (dll needs to know about main's exports)
link /nologo /dll dll.obj main.lib
rem create the executable
link /nologo main.obj dyn_link.obj
move dll.dll ..\
move main.exe ..\
cd ..
構建MSVC明確main.bat
@echo off
echo Building configuration where dll explicitly
echo links to main, but main implicitly links to dll
rd /s /q win_explicit_main
md win_explicit_main\obj
cd win_explicit_main\obj
rem compile the source code
cl /nologo /c /DEXPLICIT_MAIN ..\..\dll.c
cl /nologo /c ..\..\main.c
cl /nologo /c ..\..\dyn_link.c
rem since the dll will link dynamically and explicitly with main, there is no need
rem to create a linking library for main, and the dll can be built the regular way
link /nologo /dll dll.obj dyn_link.obj
rem create the executable (main still links with dll implicitly)
link /nologo main.obj dll.lib
move dll.dll ..\
move main.exe ..\
cd ..
構建MSVC implicit.bat
@echo off
echo Building configuration where main and
echo dll implicitly link to each other
rd /s /q win_implicit
md win_implicit\obj
cd win_implicit\obj
rem compile the source code
cl /nologo /c ..\..\dll.c
cl /nologo /c ..\..\main.c
rem normally when linking a dll, you just use the link command
rem that creates the dll and its linking library.
rem But, this dll needs to import from main, and main's linking library doesn't exist yet
rem so we create the linking library for main.obj
rem make sure that linking library knows to look for symbols in main.exe (the default would be main.dll)
lib /nologo /def /name:main.exe main.obj
rem create the dll from its object code the normal way (dll needs to know about main's exports)
link /nologo /dll dll.obj main.lib
rem create the executable (exe needs to know about dll's exports)
link /nologo main.obj dll.lib
move dll.dll ..\
move main.exe ..\
cd ..
構建MSVC static.bat
@echo off
echo Building configuration where main and dll
echo statically link to each other
rd /s /q win_static
md win_static\obj
cd win_static\obj
rem compile the source code
cl /nologo /DNO_DLL /c ..\..\dll.c
cl /nologo /DNO_DLL /c ..\..\main.c
rem create the static library
lib /nologo dll.obj
rem link the executable
link /nologo main.obj dll.lib
move main.exe ..\
cd ..
感謝您的回答。不幸的是,foo.exe並不總是調用bar.dll。但是,x總是由foo.exe使用。 – minjang 2011-02-06 06:51:04
也許這只是一個術語,但是......不需要調用DLL中的任何函數,只需要加載它。 – 2011-02-06 07:12:54
你的解決方案只適用於靜態加載(即DLL與exe同時被加載,因此全局變量在執行開始之前被鏈接)。但是OP需要一個能夠與動態加載協同工作的解決方案(使用LoadLibrary()或dlopen()來隨時加載庫),在這種情況下,全局變量不能輕易鏈接,因爲進程正在運行,Linux可以做到這一點,Windows根本無法做到這一點)。 – 2011-02-06 07:17:50