The operating system doesn’t know which language programs are written in – by the time the code hits the CPU, they all look the same


Reader Will Rayer asks about “the degree to which ‘plain vanilla’ C Windows API code works under Vista with the native look and feel.”

It works just as well as code written in any other language. The operating system doesn’t know which language programs are written in. By the time the code reaches the CPU, they all look the same. It’s just a bunch of instructions that occasionally call an API function. You can write it in C, C++, assembly, Delphi, Perl, whatever.

Of course, some languages are better-suited to calling Win32 than others. Win32 is a C-based API, in the sense that the way you call an exported function is expressed in a C header file, and __stdcall calling convention matches up reasonably well with the way C does things (once you convince your compiler to follow that convention). The way types are passed on the stack or in registers, how return values are represented, the fact that pointers are just the address of some blob of data, these all follow the C way of thinking. It stands to reason that the C language (and languages which follow in C’s footsteps, like C++) have a pretty easy time of calling Win32 exported functions.

But that doesn’t mean that those are the only languages. After all, at the end of the day, it’s all machine code. If you can write assembly language that pushes the parameters in the right format in the right order, then you can use Win32 from assembly language. (There appears to be a whole subculture devoted to this endeavor.)

Now, it is indeed the case that COM programming is much more convenient in C++ because the COM object layout matches that of many C++ compilers. But that doesn’t mean you can’t use some other language to do it. As long as that language knows how to indirect through a vtable, you can use COM objects. Indeed, the COM header files go out of their way to make sure even you old-school C programmers can call COM objects. If you define the COBJMACROS symbol, then you get access to macros like this:

#define IPersistFile_GetClassID(This,pClassID)      \
    (This)->lpVtbl -> GetClassID(This,pClassID)

This snippet from the objidl.h header file is some syntactical sugar to help C programmers use COM. Under pure C, you would retrieve the CLSID from an IPersistFile interface pointer like this:

CLSID clsid;
IPersistFile* ppf = ...;
HRESULT hr = ppf->lpVtbl->GetClassID(ppf, &clsid);

The above macro at least removes the error potential of passing the wrong this pointer:

CLSID clsid;
IPersistFile* ppf = ...;
HRESULT hr = IPersistFile_GetClassID(ppf, &clsid);

If you want to write your programs in C, you still have a lot of company. Huge chunks of Windows are still written in the C language. Not that you can tell, because once the compiler is done doing its thing, the identity of the source language is long gone.

Comments (27)
  1. Medinoc says:

    I’ve used COM from C a lot, because it’s quite fun.

    However, it becomes quite a pain in the backside when people distribute COM components with only a Type Library, and no C header: To use the functions statically, a C programmer has to regenerate the header by fiddling with OLEVIEW and MIDL!

  2. Pavel Kostromitinov says:

    Seems that the emphasis on "plain C" in original question is a bit misplaced. I’m pretty sure Will was interested more in second part – "Windows API" code. Which I presume means not using MFC/WTL/whatever.

  3. jim says:

    If you look at the Wine source, you will see tons of this stuff, Wine being written in C and constructing its COM objects "by hand", as it were.

  4. Daniel the Wise says:

    When you step into the window API with a stripped PDB you can easily see a lot of C++ code (I did not step into the kernel yet, just user-land code).

  5. Bukes says:

    Does the #import directive work with .C files?  If so, you could just #import "foo.tlb" no_namespace and have the compiler generate the class definitions for you.

    "However, it becomes quite a pain in the backside when people distribute COM components with only a Type Library, and no C header: To use the functions statically, a C programmer has to regenerate the header by fiddling with OLEVIEW and MIDL!"

  6. Gabe says:

    I think maybe he was actually asking if the Vista look requires using COM APIs.

  7. confused says:

    Where’s the link to the question?  The link above is for some site that sells a programing language.  I don’t get it.

    [Sorry, fixed. (Monday is Suggestion Box day.) -Raymond]
  8. porter says:

    > Not that you can tell, because once the compiler is done doing its thing, the identity of the source language is long gone.

    Unless you insist on using C++ exported name mangled entrypoints, where no two compilers agree.

  9. Jonathan says:

    Trying to read between the line, I assume Mr. Rayer was confused by the hype around WPF (codename Avalon), and wondering whether you have to use that to get all the new-fangled transparencies and stuff.

    I remember similar confusion when Windows Server 2003 was called "Windows .NET Server" – some people thought it was written in .NET, and that you must program in .NET to run on it. Over-hyping has its perils.

  10. Medinoc says:

    >Bukes

    >Does the #import directive work with .C files?

    >If so, you could just #import "foo.tlb" no_namespace and have the compiler generate the class definitions for you.

    No, it doesn’t work with C files, that’s the problem.

    Also, you have the same problem if you want to program in C++ with MinGW, which doesn’t support #import either.

  11. El Guapo says:

    I’m pretty sure he was asking about the *API* and not the language.

    Interesting that you wrote an entire article on what is essentially a gigantic “Nitpicker’s Corner” of your own!!!!

    [The API doesn’t know what language your program is written in either. (Not sure what the difference is between “the operating system” and “the API” here.) -Raymond]
  12. Mike Dimmick says:

    @Gabe: far from some other language being required for Vista APIs, .NET code actually has to call an unmanaged entry point to create ‘glass’ areas of a window: DwmExtendFrameIntoClientArea.

    The new ‘big buttons’ dialog boxes are created with the (C-style) TaskDialog function, or TaskDialogIndirect.

    The newest ‘open file’ and ‘save file’ dialogs are COM-based, however.

  13. Jeff Stong says:

    I once worked on a project with a mandate that Ada be the programming language used for most of the code.  We were able to create data types in Ada that looked like the COM object layout.  The Ada code was then called from MFC-based user interface code using COM.  By the time the code hit the CPU it didn’t matter that the application was a weird mix of C++ and Ada.

  14. Joe says:

    What about if/when .NET is used for the API being called? Can C directly call code in .Net assemblies? All the examples I could find involve a C++/CLR wrapper that exposes an unmanaged interface being used.

    I appreciate that it must be technically possible – but is it feasible?

  15. Sunil Joshi says:

    @Joe

    You could use the hosting (COM) API to host the CLR in your application, load the relevant assemblies and call their code.

    http://msdn.microsoft.com/en-us/library/ms404385.aspx

    It seems unnecessarily painful though.

  16. Medinoc says:

    @Joe, @Sunil Joshi: If I remember correctly, if a .Net assembly is COM-Visible, it can be called directly from an unmanaged application via COM, without having to call the hosting API from the client code (the hosting API is called by the COM infrastructure itself).

  17. Great article!

    "…because once the compiler is done doing its thing, the identity of the source language is long gone."

    (Nit-pick Warning:) I’d say this isn’t the case.  It reminds me of a newsgroup war over what language Doom was written in.  Anyone reasonable knowledgeable could easily tell it was written in C via the .exe, without even disassembling it.

    However I get the point:  It’s all machine code after the compiler is done (well, at least IL code in the case of .NET; which is pretty much the same thing).  Neat concept really.

  18. What? says:

    I’m surprised you attempted to answer this.  

    I read the question about 10 times and still don’t have even a guess as to what Will is asking.   I would say the degree to which the code works under Vista is the same as XP – very well.

  19. Cypherjb says:

    Whilst I get the idea of what you’re saying, it’s not entirely accurate.

    Although the CPU can’t ‘tell the difference’ it’s very easy to fire up a disassembler and take a look for yourself.

    Code output by a Delphi compiler looks different to that output by a C++ compiler, which looks different again to that output by a C compiler, and different again to that output by an assembler.

    Just because they all end up at the same level at the end doesn’t mean that “the identity of the source language is long gone”. It still continues to linger.

    [The identity is gone. There is no “This was originally Delphi” bit in the code stream. You can attempt to reverse-engineer the most likely language by inspecting the code style, but it’s not foolproof. (I could always write a program in assembly that “looks like” Delphi.) -Raymond]
  20. Cypherjb says:

    I guess it depends on what you define as the ‘identity’. I would say that because the original language can usually be identified under normal circumstances that at least some ‘identity’ continues to linger.

    Of course someone could go to the trouble of ‘faking’ the language, but even you have to admit seeing that in the wild would be very unlikely.

    My point was not that it was foolproof (naturally, there is lots of information that is unknown to you when disassembling a piece of software), but rather, that under normal circumstances there is still information left over that can identify the language in which the software was written.

    [While it’s true that a human being can determine the likely source language by examining the code’s style, this is not something the operating system knows anything about. It’s just code. (It’s like saying “These essays were submitted anonymously [identities removed], but if you study the writing style, you can figure out who wrote each one.” Yeah, but that doesn’t deny that the identities were removed. Now you’re doing forensics.) -Raymond]
  21. Shinobu says:

    Jim, I’ve actually found Wine quite useful when I couldn’t figure out how to use some set of functions using just the SDK.

    For those who use MinGW who have mangling issues, the killat flag can help fix that in certain scenarios.

    Also, I think Raymond’s point was not whether you could in principle determine with a certain amount of certainty what the original language was (if it was VB you will spot the pcode) but that when the code is running, it’s all machine code, no matter what compiler (or even interpreter, after all even interpreters have to execute corresponding machine code at some point) was used.

  22. Cypherjb says:

    Well, if you want to take the stance that you’re talking about the CPU not knowing the difference, not humans, that’s something different entirely.

    Of course the CPU will be indifferent, it’s a machine. ;)

    I get what you’re saying though. :)

  23. seesharp says:

    The CPU doesn’t know the program is compiled from C-code. It doesn’t help if the pe/coff format would have had a "original programming language"-property or even if you try to send the string "this program is compiled from C-code" into the cpu. The cpu cannot understand such attributes. It lacks the ability to be able to know such things.

  24. Miral says:

    As others have pointed out, the original question sounds like they were talking about the library support, not the language itself.  (It’s more complicated to write a Windows app in plain C because there are less libraries like MFC/WTL available.)

    And regarding calling into .NET code from native code: by far the simplest way is to write a mixed-mode C++ "wrapper" (either directly in the app or in a DLL).  You can pretty much just call the .NET code directly then; the compiler sorts out the details for you.

  25. quick fix says:

    The only way to fix this is if the compiler manufacturers embedded some kind of crypto certificate manifest in executable files/libraries (and checksum signed the file also), which the OS have to read and confirm which compiler was used. Then the OS can alter the code for whatever reason. This is currently not supported, a flaw.

  26. SuperKoko says:

    The question really was about getting “native look and feel” in unmanaged code with maybe some new, but old-style, API (i.e. Win64).

    With the .NET hype, one may think that WPF + a managed Microsoft language is required to make applications benefit from voice recognition, nice transparency effects in windows, and everything new in Vista, making MinGW and non-Microsoft C language implementations unable to access those extra features.

    Analogically, one can say that the MS-DOS “int 21h” API was well supported in Windows 95, and even had been extended but would produce applications with non-native look & feel (e.g. no Win32-like GUI support).

    [Imagine if only WPF applications got “native look and feel”. How many applications would have native look and feel? (What about Explorer?) -Raymond]
  27. SuperKoko says:

    "Imagine if only WPF applications got "native look and feel". How many applications would have native look and feel? (What about Explorer?)"

    I know that the answer obviously is "yes, you can get a native look & feel with the Win64 or Win32 API", but, at least, the question makes some sense.

Comments are closed.