为什么/何时不需要 __declspec( dllimport )?

发布于 2024-10-08 10:37:08 字数 1934 浏览 4 评论 0原文

在使用 server.dll 和 client.exe 的项目中,我从服务器 dll 中 dllexport 导出了服务器符号,并且没有 dllimport将其编辑到客户端 exe 中。

尽管如此,应用程序仍然可以链接并启动,没有任何问题。那么是不是就不需要dllimport了???

详细信息:

我有这个“服务器”dll:

// server.h
#ifdef SERVER_EXPORTS
  #define SERVER_API __declspec(dllexport)
#else
  #define SERVER_API // =====> not using dllimport!
#endif
class  SERVER_API CServer {
   static long s;
   public:
   CServer();
};

// server.cpp
CServer::CServer(){}

long CServer::s;

和这个客户端可执行文件:

#include <server.h>
int main() {
   CServer s;
}

服务器命令行:

cl.exe /Od  /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" 
 /D "SERVER_EXPORTS" /D "_UNICODE" /D "UNICODE" /D "_WINDLL" 
 /Gm /EHsc /RTC1 /MDd /Yu"stdafx.h" 
 /Fp"Debug\server.pch" /Fo"Debug\\" /Fd"Debug\vc80.pdb" 
 /W3 /nologo /c /Wp64 /ZI /TP /errorReport:prompt

cl.exe /OUT:"U:\libs\Debug\server.dll" /INCREMENTAL:NO /NOLOGO /DLL 
/MANIFEST /MANIFESTFILE:"Debug\server.dll.intermediate.manifest" 
/DEBUG /PDB:"u:\libs\Debug\server.pdb" 
/SUBSYSTEM:WINDOWS /MACHINE:X86 /ERRORREPORT:PROMPT 
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib 
shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

客户端命令行:

cl.exe /Od /I "..\server" 
 /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" 
 /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc80.pdb" /W3 /c /Wp64 /ZI /TP 
 .\client.cpp

cl.exe /OUT:"U:\libs\Debug\Debug\client.exe" /INCREMENTAL 
/LIBPATH:"U:\libs\Debug" 
/MANIFEST /MANIFESTFILE:"Debug\client.exe.intermediate.manifest" 
/DEBUG /PDB:"u:\libs\debug\debug\client.pdb" 
/SUBSYSTEM:CONSOLE /MACHINE:X86 
server.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib 
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

In a project using a server.dll and a client.exe, I have dllexported a server symbol from the server dll, and not dllimported it into the client exe.

Still, the application links, and starts, without any problem. Is dllimport not needed, then???

Details:

I have this 'server' dll:

// server.h
#ifdef SERVER_EXPORTS
  #define SERVER_API __declspec(dllexport)
#else
  #define SERVER_API // =====> not using dllimport!
#endif
class  SERVER_API CServer {
   static long s;
   public:
   CServer();
};

// server.cpp
CServer::CServer(){}

long CServer::s;

and this client executable:

#include <server.h>
int main() {
   CServer s;
}

The server command line:

cl.exe /Od  /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" 
 /D "SERVER_EXPORTS" /D "_UNICODE" /D "UNICODE" /D "_WINDLL" 
 /Gm /EHsc /RTC1 /MDd /Yu"stdafx.h" 
 /Fp"Debug\server.pch" /Fo"Debug\\" /Fd"Debug\vc80.pdb" 
 /W3 /nologo /c /Wp64 /ZI /TP /errorReport:prompt

cl.exe /OUT:"U:\libs\Debug\server.dll" /INCREMENTAL:NO /NOLOGO /DLL 
/MANIFEST /MANIFESTFILE:"Debug\server.dll.intermediate.manifest" 
/DEBUG /PDB:"u:\libs\Debug\server.pdb" 
/SUBSYSTEM:WINDOWS /MACHINE:X86 /ERRORREPORT:PROMPT 
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib 
shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

Client command line:

cl.exe /Od /I "..\server" 
 /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" 
 /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc80.pdb" /W3 /c /Wp64 /ZI /TP 
 .\client.cpp

cl.exe /OUT:"U:\libs\Debug\Debug\client.exe" /INCREMENTAL 
/LIBPATH:"U:\libs\Debug" 
/MANIFEST /MANIFESTFILE:"Debug\client.exe.intermediate.manifest" 
/DEBUG /PDB:"u:\libs\debug\debug\client.pdb" 
/SUBSYSTEM:CONSOLE /MACHINE:X86 
server.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib 
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

坏尐絯℡ 2024-10-15 10:37:08

__declspec(dllimport) 是一个客户端 MSVC 属性,可以为导入的代码和数据指定。

代码不需要它。这是一种优化;客户端编译器提示函数调用不是直接的而是导入的。名为 foo() 的函数的导入函数指针将为 __imp_foo。如果没有提示,则会创建一个 thunk 来加载 __imp_foo 中的地址并跳转到该地址。通过提示,将跳过 thunk,并生成通过 IAT1 条目的间接调用,即内联 thunk。这是时间优化,而不是空间优化。

从 DLL 导入的数据需要它。

这个 博客文章有详细信息。

1:程序导入地址表

__declspec(dllimport) is a client-side MSVC attribute that can be specified for imported code and data.

It isn't required for code. It is an optimization; a client-side compiler hint that a function call isn't direct but imported. The imported function pointer for a function named foo() will be __imp_foo. Without the hint, a thunk is created to load the address in __imp_foo and jump to it. With the hint the thunk is skipped and an indirect call through the IAT1 entry is generated i.e. the thunk is inlined. It is a time optimization, not space.

It's required for data that's imported from a DLL.

This blog post has the details.

1: Import Address Table of a program

任性一次 2024-10-15 10:37:08

我也想知道这个问题。我还删除了 __declspec(dllimport) 指令,并且非常惊讶地发现依赖于另一个 dll (glib) 中的函数的 dll (gmodule) 编译并运行(特别是在wireshark 中)没有问题。这是 MS 的引用:

__declspec(dllimport) is ALWAYS required to access exported DLL data.

不知道为什么 MS 这么说,因为在其他页面上他们声明该指令是不必要的。无论如何,我的库不仅在没有 dllimport 的情况下运行,而且我已经很多年没有看到“__imp”符号了,而以前我经常偶然发现它(或者它在我身上)。这是怎么回事?答案就在这里:

That's why using __declspec(dllimport) is better: because the linker doesn't generate a thunk if it's not required. There's no thunk and no jmp instruction, so the code is smaller and faster. You can also get the same effect WITHOUT __declspec(dllimport) by using whole program optimization. For more information, see /GL (Whole Program Optimization).

现在说得通了。我在所有项目中都使用 /GL (+ /LTCG)。 的答案。

when is __declspec( dllimport ) not needed?

这就是主题问题“当使用整个程序优化时”

I was wondering about this too. I also removed the __declspec(dllimport) instruction and was very surprised to see that a dll (gmodule) relying on functions in another dll (glib) compiled and ran (in wireshark in particular) without problems. Here's a quote by MS:

__declspec(dllimport) is ALWAYS required to access exported DLL data.

No idea why MS says this, because on other pages they state the instruction is not necessary. Regardless, not only does my library run without dllimport, but I haven't seen an "__imp" symbol in ages, while formerly I was constantly stumbling upon it (or it on me). What happened to it? The answer is here:

That's why using __declspec(dllimport) is better: because the linker doesn't generate a thunk if it's not required. There's no thunk and no jmp instruction, so the code is smaller and faster. You can also get the same effect WITHOUT __declspec(dllimport) by using whole program optimization. For more information, see /GL (Whole Program Optimization).

Now it makes sense. I am using /GL (+ /LTCG) on all projects. So that's the answer to the topic question

when is __declspec( dllimport ) not needed?

When whole program optimization is utilised.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文