{"id":30363,"date":"2006-07-26T10:00:00","date_gmt":"2006-07-26T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2006\/07\/26\/what-happens-when-you-get-dllimport-wrong\/"},"modified":"2006-07-26T10:00:00","modified_gmt":"2006-07-26T10:00:00","slug":"what-happens-when-you-get-dllimport-wrong","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20060726-00\/?p=30363","title":{"rendered":"What happens when you get dllimport wrong?"},"content":{"rendered":"<p>Now that we&#8217;ve learned what the <code>dllimport<\/code> declaration specifier does, what if you get it wrong?\n If you forget to declare a function as <code>dllimport<\/code>, then you&#8217;re basically making the compiler act like a naive compiler that doesn&#8217;t understand <code>dllimport<\/code>. When the linker goes to resolve the external reference for the function, it will use the stub from the import library, and everything will work as before. You do miss out on the optimization that <code>dllimport<\/code> enables, but the code will still run. You&#8217;re just running in naive mode.\n (There are still some header files in the Platform SDK that neglect to use the <code>dllimport<\/code> declaration specifier. As a result, anybody who uses those header files to import functions from the corresponding DLL will be operating in &#8220;naive mode&#8221;. Hopefully the people responsible for those header files will recognize themselves in this parenthetical and fix the problem for a future release of the Platform SDK.)\n Now, what about the reverse problem? What if you declare a function as <code>dllimport<\/code> when it really isn&#8217;t? The linker detects this since it sees an attempt to import a <code>__imp__FunctionName<\/code> symbol and can&#8217;t find one, though it can find the normal <code>FunctionName<\/code> symbol. When this happens, the linker raises <a href=\"http:\/\/msdn.microsoft.com\/library\/en-us\/vccore\/html\/vcerrLinkerToolsWarningLNK4217.asp\"> warning LNK4217<\/a>. It recovers from this error by simply manufacturing a fake <code>__imp__FunctionName<\/code> variable and initializing it with the address of the <code>FunctionName<\/code> function. In effect, you&#8217;ve imported the function from yourself. Your code now goes through all the gyrations associated with calling an imported function unnecessarily; it could have just called <code>FunctionName<\/code> directly.\n (There are cases where the linker can be a little smarter. For example, if it sees a <code>call [__imp__FunctionName]<\/code>, it can change it to <code>call FunctionName + nop<\/code>. The <code>nop<\/code> is necessary because the <code>call [__imp__FunctionName]<\/code> instruction is six bytes long, whereas <code>call FunctionName<\/code> is only five. The extra <code>nop<\/code> gets everything back in sync.)\n Thus, in both cases where you mess up the <code>dllimport<\/code> declaration specifier, the linker manages to recover from your mistake, and your program does run fine, though the patching up did cost you in code size and efficiency.\n (All this discussion is for x86, by the way. Other architectures have different quirks.)<\/p>\n<p> Next time, more on import libraries, and exposing some &#8220;little white lies&#8221; I&#8217;ve been telling. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Now that we&#8217;ve learned what the dllimport declaration specifier does, what if you get it wrong? If you forget to declare a function as dllimport, then you&#8217;re basically making the compiler act like a naive compiler that doesn&#8217;t understand dllimport. When the linker goes to resolve the external reference for the function, it will use [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-30363","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>Now that we&#8217;ve learned what the dllimport declaration specifier does, what if you get it wrong? If you forget to declare a function as dllimport, then you&#8217;re basically making the compiler act like a naive compiler that doesn&#8217;t understand dllimport. When the linker goes to resolve the external reference for the function, it will use [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/30363","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=30363"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/30363\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=30363"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=30363"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=30363"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}