存在来自静态库的功能独立地在里面:
-
.dll- 从另一个加载时它会起作用应用程序
-
应用程序- 它在不加载时工作.dll
所以,我发现你遇到的行为很正常(更多:每个人都会发生这种情况.dll包含来自静态的代码库进程正在加载)。
这是MCVE([SO]: How to create a Minimal, Reproducible Example (reprex (mcve))) 我在说。
lib00.h:
#pragma once
#if defined(_WIN32)
# if defined(LIB00_STATIC)
# define LIB00_EXPORT_API
# else
# if defined(LIB00_EXPORTS)
# define LIB00_EXPORT_API __declspec(dllexport)
# else
# define LIB00_EXPORT_API __declspec(dllimport)
# endif
# endif
#else
# define LIB00_EXPORT_API
#endif
LIB00_EXPORT_API int libFunc();
lib00.c:
#include <inttypes.h>
#include <stdio.h>
#define LIB00_EXPORTS
#include "lib00.h"
static int gVar = 0;
int libFunc()
{
printf(" %s - var (0x%016lX): %d\n", __FUNCTION__, (uintptr_t)(&gVar), gVar);
return gVar++;
}
dll00.c:
#include <stdio.h>
#include "lib00.h"
#if defined(_WIN32)
# define DLL00_EXPORT_API __declspec(dllexport)
#else
# define DLL00_EXPORT_API
#endif
#if defined(__cplusplus)
extern "C" {
#endif
DLL00_EXPORT_API void dllFunc();
#if defined(__cplusplus)
}
#endif
void dllFunc()
{
printf("Call libFunc from .DLL: %d\n", libFunc());
}
main00.c:
#include <stdio.h>
#if defined (_WIN32)
# include <windows.h>
# define DLLPTR HMODULE
# define dlsym GetProcAddress
# define dlclose FreeLibrary
#else
# include <dlfcn.h>
# define DLLPTR void*
#endif
#include "lib00.h"
typedef int (*DllFuncPtr)();
int main(int argc, char **argv)
{
DLLPTR pDll00 = NULL;
DllFuncPtr pDllFunc = NULL;
const int count = 3;
if (argc > 1) {
#if defined (_WIN32)
pDll00 = LoadLibrary(argv[1]);
#else
int dlopen_flags = RTLD_NOW; //RTLD_LAZY;
//dlopen_flags |= RTLD_GLOBAL;
pDll00 = dlopen(argv[1], dlopen_flags);
#endif
if (pDll00) {
pDllFunc = (DllFuncPtr)dlsym(pDll00, "dllFunc");
} else {
printf("Error loading .dll\n");
#if defined (_WIN32)
printf("Error: %d\n", GetLastError());
#else
printf("%s\n", dlerror());
#endif
}
}
for (int i = 0; i < count; ++i) {
if (pDllFunc)
pDllFunc();
printf("Call libFunc from .EXE: %d\n", libFunc());
}
if (pDll00)
dlclose(pDll00);
printf("\nDone.\n\n");
return 0;
}
别介意#定义s,他们(大部分)是为了赢.
输出:
(qaic-env) [cfati@cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q073944078]> ~/sopr.sh
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###
[064bit prompt]> ls
dll00.c lib00.c lib00.h main00.c
[064bit prompt]>
[064bit prompt]> # Build static lib00
[064bit prompt]>
[064bit prompt]> gcc -c -DLIB00_STATIC -o lib00s.o lib00.c
[064bit prompt]> ar rcs lib00s.a lib00s.o
[064bit prompt]> gcc -DLIB00_STATIC -fPIC -shared -o dll00s.so dll00.c lib00s.a
[064bit prompt]> gcc -DLIB00_STATIC -o app00s main00.c -ldl lib00s.a
[064bit prompt]> ls
app00s dll00.c dll00s.so lib00.c lib00.h lib00s.a lib00s.o main00.c
[064bit prompt]>
[064bit prompt]> ./app00s
libFunc - var (0x00005580D94BA014): 0
Call libFunc from .EXE: 0
libFunc - var (0x00005580D94BA014): 1
Call libFunc from .EXE: 1
libFunc - var (0x00005580D94BA014): 2
Call libFunc from .EXE: 2
Done.
[064bit prompt]> ./app00s ./dll00s.so
libFunc - var (0x00007F4559918034): 0
Call libFunc from .DLL: 0
libFunc - var (0x000056083959F014): 0
Call libFunc from .EXE: 0
libFunc - var (0x00007F4559918034): 1
Call libFunc from .DLL: 1
libFunc - var (0x000056083959F014): 1
Call libFunc from .EXE: 1
libFunc - var (0x00007F4559918034): 2
Call libFunc from .DLL: 2
libFunc - var (0x000056083959F014): 2
Call libFunc from .EXE: 2
Done.
[064bit prompt]>
[064bit prompt]> # Build dynamic lib00
[064bit prompt]>
[064bit prompt]> gcc -fPIC -shared -o lib00.so lib00.c
[064bit prompt]> gcc -fPIC -shared -o dll00.so dll00.c lib00.so
[064bit prompt]> gcc -o app00 main00.c -ldl lib00.so
[064bit prompt]> ls
app00 app00s dll00.c dll00.so dll00s.so lib00.c lib00.h lib00.so lib00s.a lib00s.o main00.c
[064bit prompt]>
[064bit prompt]> ./app00
./app00: error while loading shared libraries: lib00.so: cannot open shared object file: No such file or directory
[064bit prompt]> LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:. ./app00
libFunc - var (0x00007FDCC6DC202C): 0
Call libFunc from .EXE: 0
libFunc - var (0x00007FDCC6DC202C): 1
Call libFunc from .EXE: 1
libFunc - var (0x00007FDCC6DC202C): 2
Call libFunc from .EXE: 2
Done.
[064bit prompt]> LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:. ./app00 ./dll00.so
libFunc - var (0x00007FE562D1E02C): 0
Call libFunc from .DLL: 0
libFunc - var (0x00007FE562D1E02C): 1
Call libFunc from .EXE: 1
libFunc - var (0x00007FE562D1E02C): 2
Call libFunc from .DLL: 2
libFunc - var (0x00007FE562D1E02C): 3
Call libFunc from .EXE: 3
libFunc - var (0x00007FE562D1E02C): 4
Call libFunc from .DLL: 4
libFunc - var (0x00007FE562D1E02C): 5
Call libFunc from .EXE: 5
Done.
因此,在.dll解决问题。
有了这两种构建,我想看看组合事物时会发生什么:
[064bit prompt]> _LD_LIBRARY_PATH=${LD_LIBRARY_PATH}
[064bit prompt]> LD_LIBRARY_PATH=${_LD_LIBRARY_PATH}:.
[064bit prompt]> for g in app00s app00; do for i in dll00s.so dll00.so; do echo ./${g} ./${i}; ./${g} ./${i}; done done
./app00s ./dll00s.so
libFunc - var (0x00007F5608ED4034): 0
Call libFunc from .DLL: 0
libFunc - var (0x000055C0AFBCD014): 0
Call libFunc from .EXE: 0
libFunc - var (0x00007F5608ED4034): 1
Call libFunc from .DLL: 1
libFunc - var (0x000055C0AFBCD014): 1
Call libFunc from .EXE: 1
libFunc - var (0x00007F5608ED4034): 2
Call libFunc from .DLL: 2
libFunc - var (0x000055C0AFBCD014): 2
Call libFunc from .EXE: 2
Done.
./app00s ./dll00.so
libFunc - var (0x00007FB3DBAB102C): 0
Call libFunc from .DLL: 0
libFunc - var (0x000055BA0A2C5014): 0
Call libFunc from .EXE: 0
libFunc - var (0x00007FB3DBAB102C): 1
Call libFunc from .DLL: 1
libFunc - var (0x000055BA0A2C5014): 1
Call libFunc from .EXE: 1
libFunc - var (0x00007FB3DBAB102C): 2
Call libFunc from .DLL: 2
libFunc - var (0x000055BA0A2C5014): 2
Call libFunc from .EXE: 2
Done.
./app00 ./dll00s.so
libFunc - var (0x00007F52A75A302C): 0
Call libFunc from .DLL: 0
libFunc - var (0x00007F52A75A302C): 1
Call libFunc from .EXE: 1
libFunc - var (0x00007F52A75A302C): 2
Call libFunc from .DLL: 2
libFunc - var (0x00007F52A75A302C): 3
Call libFunc from .EXE: 3
libFunc - var (0x00007F52A75A302C): 4
Call libFunc from .DLL: 4
libFunc - var (0x00007F52A75A302C): 5
Call libFunc from .EXE: 5
Done.
./app00 ./dll00.so
libFunc - var (0x00007FE3C8C9602C): 0
Call libFunc from .DLL: 0
libFunc - var (0x00007FE3C8C9602C): 1
Call libFunc from .EXE: 1
libFunc - var (0x00007FE3C8C9602C): 2
Call libFunc from .DLL: 2
libFunc - var (0x00007FE3C8C9602C): 3
Call libFunc from .EXE: 3
libFunc - var (0x00007FE3C8C9602C): 4
Call libFunc from .DLL: 4
libFunc - var (0x00007FE3C8C9602C): 5
Call libFunc from .EXE: 5
Done.
对我来说,结果有点奇怪,正如我所期待的 3rd运行与前 2 个相同。我一定遗漏了有关符号解析的内容。最有可能的是,事情可以通过改变来改变打开标志或通过修改静态库象征 (库函数) 可见性(这将需要部分或全部重建)。
我做了同样的事情赢:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q073944078]> sopr.bat
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###
[prompt]> "c:\Install\pc032\Microsoft\VisualStudioCommunity\2019\VC\Auxiliary\Build\vcvarsall.bat" x64 > nul
[prompt]> dir /b
app00
app00s
dll00.c
dll00.so
dll00s.so
lib00.c
lib00.h
lib00.so
lib00s.a
lib00s.o
main00.c
[prompt]>
[prompt]> cl -c /nologo /DLIB00_STATIC /MD lib00.c /Folib00s.obj
lib00.c
lib00.c(11): warning C4477: 'printf' : format string '%016lX' requires an argument of type 'unsigned long', but variadic argument 2 has type 'uintptr_t'
lib00.c(11): note: consider using '%llX' in the format string
lib00.c(11): note: consider using '%IX' in the format string
lib00.c(11): note: consider using '%I64X' in the format string
[prompt]> lib /NOLOGO /OUT:lib00s.lib lib00s.obj
[prompt]> cl /nologo /MD /DDLL lib00.c /link /NOLOGO /DLL /OUT:lib00.dll
lib00.c
lib00.c(11): warning C4477: 'printf' : format string '%016lX' requires an argument of type 'unsigned long', but variadic argument 2 has type 'uintptr_t'
lib00.c(11): note: consider using '%llX' in the format string
lib00.c(11): note: consider using '%IX' in the format string
lib00.c(11): note: consider using '%I64X' in the format string
Creating library lib00.lib and object lib00.exp
[prompt]>
[prompt]> cl /nologo /MD /DDLL /DLIB00_STATIC dll00.c /link /NOLOGO /DLL /OUT:dll00s.dll lib00s.lib
dll00.c
Creating library dll00s.lib and object dll00s.exp
[prompt]> cl /nologo /MD /DDLL dll00.c /link /NOLOGO /DLL /OUT:dll00.dll lib00.lib
dll00.c
Creating library dll00.lib and object dll00.exp
[prompt]>
[prompt]> cl /nologo /MD /W0 /DLIB00_STATIC main00.c /link /NOLOGO /OUT:app00s.exe lib00s.lib
main00.c
[prompt]> cl /nologo /MD /W0 main00.c /link /NOLOGO /OUT:app00.exe lib00.lib
main00.c
[prompt]>
[prompt]> dir /b
app00
app00.exe
app00s
app00s.exe
dll00.c
dll00.dll
dll00.exp
dll00.lib
dll00.obj
dll00.so
dll00s.dll
dll00s.exp
dll00s.lib
dll00s.so
lib00.c
lib00.dll
lib00.exp
lib00.h
lib00.lib
lib00.obj
lib00.so
lib00s.a
lib00s.lib
lib00s.o
lib00s.obj
main00.c
main00.obj
[prompt]>
[prompt]> for %g in (app00s.exe app00.exe) do (for %i in (dll00s.dll dll00.dll) do (echo %g %i && %g %i))
[prompt]> (for %i in (dll00s.dll dll00.dll) do (echo app00s.exe %i && app00s.exe %i ) )
[prompt]> (echo app00s.exe dll00s.dll && app00s.exe dll00s.dll )
app00s.exe dll00s.dll
libFunc - var (0x000000009D343080): 0
Call libFunc from .DLL: 0
libFunc - var (0x00000000DFD430D0): 0
Call libFunc from .EXE: 0
libFunc - var (0x000000009D343080): 1
Call libFunc from .DLL: 1
libFunc - var (0x00000000DFD430D0): 1
Call libFunc from .EXE: 1
libFunc - var (0x000000009D343080): 2
Call libFunc from .DLL: 2
libFunc - var (0x00000000DFD430D0): 2
Call libFunc from .EXE: 2
Done.
[prompt]> (echo app00s.exe dll00.dll && app00s.exe dll00.dll )
app00s.exe dll00.dll
libFunc - var (0x0000000099BE3060): 0
Call libFunc from .DLL: 0
libFunc - var (0x00000000DFD430D0): 0
Call libFunc from .EXE: 0
libFunc - var (0x0000000099BE3060): 1
Call libFunc from .DLL: 1
libFunc - var (0x00000000DFD430D0): 1
Call libFunc from .EXE: 1
libFunc - var (0x0000000099BE3060): 2
Call libFunc from .DLL: 2
libFunc - var (0x00000000DFD430D0): 2
Call libFunc from .EXE: 2
Done.
[prompt]> (for %i in (dll00s.dll dll00.dll) do (echo app00.exe %i && app00.exe %i ) )
[prompt]> (echo app00.exe dll00s.dll && app00.exe dll00s.dll )
app00.exe dll00s.dll
libFunc - var (0x0000000099BE3080): 0
Call libFunc from .DLL: 0
libFunc - var (0x000000009D343060): 0
Call libFunc from .EXE: 0
libFunc - var (0x0000000099BE3080): 1
Call libFunc from .DLL: 1
libFunc - var (0x000000009D343060): 1
Call libFunc from .EXE: 1
libFunc - var (0x0000000099BE3080): 2
Call libFunc from .DLL: 2
libFunc - var (0x000000009D343060): 2
Call libFunc from .EXE: 2
Done.
[prompt]> (echo app00.exe dll00.dll && app00.exe dll00.dll )
app00.exe dll00.dll
libFunc - var (0x000000009D343060): 0
Call libFunc from .DLL: 0
libFunc - var (0x000000009D343060): 1
Call libFunc from .EXE: 1
libFunc - var (0x000000009D343060): 2
Call libFunc from .DLL: 2
libFunc - var (0x000000009D343060): 3
Call libFunc from .EXE: 3
libFunc - var (0x000000009D343060): 4
Call libFunc from .DLL: 4
libFunc - var (0x000000009D343060): 5
Call libFunc from .EXE: 5
Done.
在这里,事情看起来和我期望的一样。