Git Product home page Git Product logo

Comments (11)

nigels-com avatar nigels-com commented on June 14, 2024 1

the compiler generates slightly different code when it needs to reference an imported function, since the compiler is aware of the special way imported functions are implemented.

https://devblogs.microsoft.com/oldnewthing/20060724-00/?p=30403

If you forget to declare a function as dllimport, then you’re basically making the compiler act like a naive compiler that doesn’t understand dllimport. 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 dllimport enables, but the code will still run. You’re just running in naive mode.

https://devblogs.microsoft.com/oldnewthing/20060726-00/?p=30363

The fact that names in import libraries are decorated means that it is doubly crucial that you use the official import library for the DLL you wish to use rather than trying to manufacture one with an import library generation tool. As we noted earlier, the tool won’t know whether the ordinal assigned to a named function was by design or merely coincidental.

https://devblogs.microsoft.com/oldnewthing/20060727-00/?p=30343

from glew.

nigels-com avatar nigels-com commented on June 14, 2024

Is there a specific issue you're having?

The binary API is essentially frozen, there would a lot of reluctance to change this.

from glew.

JakeSmarter avatar JakeSmarter commented on June 14, 2024

I am not requesting to change the binary API. I am just saying that there is neither need for dllimport nor GLEW_STATIC, especially when you build GLEW as a static library. Because when you compile an app for Windows to consume GLEW, by default (without GLEW_STATIC defined) you get __imp_ prefixed external symbols. And, when you try to link your app to GLEW statically you get unresolved symbols. At the same time, you do not need dllimport when writing code which is going to access symbols in a DLL. dllimport is a relic of Cygwin. Some will argue that it enables application developers to select on a per symbol level the source of a symbol in the source code when linking to static and dynamic libraries at the same time. However, this decision should and can still be made by the application developer (GLEW’s consumer) in their own code, not in GLEW’s headers.

from glew.

nigels-com avatar nigels-com commented on June 14, 2024

My perception of dllimport is that it's rather more conventional than being a "relic of Cygwin". But I do follow your reasoning and think it has technical merit. The practical problem is that if I get this wrong and widespread breakage results, I will likely get flooded with nasty outrage, the internet being how it is. I don't think using and requiring GLEW_STATIC is such a burden, but I admit that I just expect Windows development to be needlessly "annoying" like this.

from glew.

nigels-com avatar nigels-com commented on June 14, 2024

I guess one thing for me to revise is the implications of having the __imp_ prefix, or not. I do regard that as an ABI change, but what is the risk of that change more broadly?

from glew.

nigels-com avatar nigels-com commented on June 14, 2024

https://learn.microsoft.com/en-us/cpp/build/importing-into-an-application-using-declspec-dllimport?view=msvc-170

Using __declspec(dllimport) is optional on function declarations, but the compiler produces more
efficient code if you use this keyword. However, you must use __declspec(dllimport) for the importing
executable to access the DLL's public data symbols and objects. Note that the users of your DLL still
need to link with an import library.

from glew.

JakeSmarter avatar JakeSmarter commented on June 14, 2024

https://learn.microsoft.com/en-us/cpp/build/importing-and-exporting?view=msvc-170

Use the keywords __declspec(dllimport) or __declspec(dllexport) in a function definition in the main application

dllexport is meant for and still used by library authors. dllimport is/was meant for application authors, especially in the days before import libraries (like WinNT 3.51 and earlier). Application authors should decide which symbol and which not to import from a DLL. This decision should not be made by library headers. Today, this decision is usually made at link‑time by choosing either a static library or an import library (hence the word import in the name 😉). GLEW produces an import library by default. So yes, technically libraries can make this decision (as GLEW does) but by convention they do not and should not, especially when they provide an import library. In legacy toolchains, I think in pre‑MSVC 6.0, you had to use dllimport at least on data symbols (this is probably also a reason why dllimports have been added throughout GLEW). However, I think since MSVC 6.0, you do not have to do even this anymore. The linkers of all toolchains have been upgraded to do this automatically long time ago. All extern symbols are just resolved at link‑time, no matter whether they are found in a DLL or a static library. Furthermore, I think since MSVC 7.0 or maybe even earlier, Microsoft has stopped adding __imp_ prefixed symbols to their import library releases.
This is the only hint of that transition I could find now. Argh, if I could only find a properly archived MSDN somewhere… There was a nice article about this.

For example, the Windows SDK headers do not use dllimport although virtually all symbols in the headers can only be found in DLLs, and at link‑time in import libraries.

dllimport should also enable you to link to a DLL, in other words import a symbol, if you do not have an import library of that particular DLL. But, since GLEW produces an import library there is no need for doubling the effort (and creating confusion).

…, but doing so allows the compiler to generate better code.
…, but the compiler produces more efficient code if you use this keyword.

This claim in the docs is basically unsubstantiated and I am not even sure where this may be coming from. Maybe symbol lookup at link‑time can happen a bit faster? But, the compiler does not really have much to do with that.

My perception of dllimport is that it's rather more conventional than being a “relic of Cygwin”.

It is a “relic of Cygwin” in that sense that Cygwin kept using this explicit symbol importing mechanism when Microsoft and other toolchain makers have already moved on long time ago to import libraries.

what is the risk of that change more broadly?

You should not break much because all modern toolchains do not need dllimport to work properly. People using ancient toolchains may need this but then 🤔 who would want to use obsolete toolchains and the artifacts they produce? In this case people can still add dllimport to the symbols they need in their code.

from glew.

JakeSmarter avatar JakeSmarter commented on June 14, 2024

Although these are not the articles I had in mind they are also definitely enlightening. Thank you for digging these up. 👍

So, I guess we learn that dllimport reduces one level of indirection, which does result in less binary code produced by the compiler, however the gains are minuscule. This reminds me that I might have read about dllimport’s obsolescence in the context of Microsoft’s LTCG or GCC’s LTO. Because like the name says, there is code generation involved when linking. So, maybe it was in that context. Because if my memory serves me right, during LTCG or LTO the linker effectively creates __imp_ prefixed symbols before finally linking which has exactly the same effect Raymond Chen describes. I will have to search more on LTO.

Though, much of what Raymond Chen talks about there is often closely related to x86 (only). So, I guess one has to be careful when dealing with other architectures.

Interestingly, he says something about that I have also observed and mentioned this:

(There are still some header files in the Platform SDK that neglect to use the dllimport declaration specifier. As a result, anybody who uses those header files to import functions from the corresponding DLL will be operating in “naive mode”. 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.)

🤭 I guess his hopes have been in vain to this day. The Platform SDK (now renamed to the Windows SDK) headers still have not been attributed with dllimport. So, apparently it has been deemed not as important as things may seem, probably due to the linker upgrades over time.

Anyhow, having dllimport declarations in a header does not do any harm per se, it is just that you have to basically guard those symbols with a macro and define it when you want to link them statically. I guess, it is an inconvenience one can live with but with the downside that you always have to dig up the exact static guarding macro’s name while at the same time this problem has been solved in modern linkers.

from glew.

nigels-com avatar nigels-com commented on June 14, 2024

I'm sincere in saying that I didn't intend to tour this particular rabbit-hole, but a bit glad to have had a look and a conversation.

So far I'm leaning towards status-quo. Some reasoning:

  1. It still seems to be what Microsoft recommends as best-practice.
  2. GLEW is a C library intended for maximum portability, including obsolete compilers.
  3. There isn't much reward (for me) in making a change, but risk of breakage, and resulting maintainer grief.
  4. GLEW has been around a long time, has accumulated a fairly large install-base, I think that stability is generally valued.
  5. I don't happen to have old MS compilers to test with, and not motivated to go above and beyond to test for real.
  6. It's irritating to deal with the import/export/static macro stuff, but it's nothing new or unique to GLEW.
  7. Considering it's still required for data exports, doesn't seem unreasonable to be consistent.

Having said all that, I'm not sure dllimport is completely obsolete, but probably still appropriate for such an entrenched and old-school software module.

from glew.

JakeSmarter avatar JakeSmarter commented on June 14, 2024

Yeah, everything you are saying sounds reasonable und I fully understand that you want to minimize any chances of braking something.

I have opened this issue because GLEW was the only dependency in the project I am currently working on that requires you to define a macro at compile‑time when you intend to link statically later, which in my humble experience is quite unusual. It took me more than a day to figure out what was going on. Maybe I should have looked into GLEW’s documentation and source code a little bit earlier but since it is a kind of inherited project there was seemingly no reason for me to look more closely into this particular dependency than others. Anyhow, I have solved the issue in the project and have learned something new about dllimport. 😄

This should close #385. Thank you for your assistance. 👍

from glew.

JakeSmarter avatar JakeSmarter commented on June 14, 2024

The Platform SDK (now renamed to the Windows SDK) headers still have not been attributed with dllimport.

Just FYI, the function declarations in the Windows SDK headers have been indeed specified with dllimport. I must have missed something the first time or have been only looking at the WINAPI macro. The WINBASEAPI and DECLSPEC_IMPORT macros are substituted with dllimport specifiers.

I wonder however how do they handle function declarations that can be linked dynamically and statically without the need for an additional macro because the Windows SDK ships with a (though obsolete but nevertheless existing) static C runtime library. And, I do not recall defining one just in order to link statically later. Well, it was long time ago. 😀

from glew.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.