C和Windows API之间的关系是什么?

11

我研究了SO上的一些其他问题,但不清楚C是在WINAPI之上、之下还是并行存在。例如,有人能否使用纯C编写能够打开窗口的程序,还是必须使用Windows API?

我注意到在打开文件方面,C库版本(fopen)与Windows API版本(CreateFile)之间存在相似之处,这让我想知道其中一个是否只是另一个的包装器。有人知道吗?

如果Windows正在运行,程序员是否被迫使用Windows API才能在其上运行程序,还是程序员不能使用Windows API并直接访问硬件(即Windows操作系统是否保护对硬件的访问)?

在Windows CE的不同版本中,哪个更具可移植性?我找到的文档(现已更改)曾经说CreateFile仅适用于Windows CE 2.0版及以上版本(在此处查看: http://msdn.microsoft.com/en-us/library/ms959950.aspx - 请注意链接底部的注释显示支持的版本信息已更改)。那么,应该在Windows CE 1版本中使用什么?换句话说,使用c函数或标记为WINAPI的函数进行编程,在所有Windows CE版本中都更容易工作?

我在一本有关编程Windows CE的书中读到以下内容,这使我感到困惑,因此可以通过理解以下内容来更好地理解上述所有问题:

Windows CE支持大部分在Windows NT和Windows 98上发现的文件I/O函数。所有支持的Win32 API调用,例如CreateFile、ReadFile、WriteFile和CloseFile都可以使用。然而,Windows CE程序员必须注意一些不同之处。首先,标准的C文件I/O函数,如fopen、fread和fprintf,在Windows CE下不受支持。同样,旧的Win16标准_lread、_lwrite和_llseek也不受支持。这并不是一个很大的问题,因为所有这些函数都可以通过使用少量代码包装Windows CE文件函数来轻松实现。

“包装”意味着需要有东西来包装,鉴于Win16和C库似乎不可用,是否他是在建议把CreateFile函数封装起来,以便创建类似于fopen的C版本? (我知道的唯一其他的方法是汇编语言,如果他建议包装它,那么就不会用这种随意的方式写了。)

基于以上内容,C语言(语法、数据结构、控制流)、C函数库(例如fopen)和Windows API(例如CreateFile)之间的依赖关系是什么?


4
请更新问题。您拥有此问题。不要添加评论。请通过您对可移植性的定义实际改进问题。 - S.Lott
10个回答

18

C语言比Windows存在的时间更久。Windows API是用C语言编写的一组库。根据Microsoft公开文档或API所提供的功能,可能有可能复制其功能。在某个层面上,fopen()CreateFile()可能会调用相同或类似的操作系统服务,但它们不太可能是彼此的严格包装器。要绕过Windows API直接访问硬件可能会很困难,但通过足够的时间和编程工作,任何事情都有可能。


5
即使在文字显示器普及之前,printf 之所以是 printf 而不是 displayf,是有原因的。 - Cogwheel
11
实际上,fopen 函数的实现直接使用了 CreateFile 函数。如果你跟随其实现过程,最终会在 CRT 源码的 open.c 文件中调用到 CreateFile 函数(该函数包含于 Visual Studio 中)。 - Dean Harding
4
我在上面的评论显然只适用于Windows。使用fopen的重点是它在任何C实现中都可用,并使用该平台上打开文件的“本地”方法...在Windows上,是CreateFile,在Linux上是open,等等... - Dean Harding
@Dean,感谢你提供关于CreateFile的信息;我从未编写过Windows API程序,所以只是猜测。 - Carl Norum
Dean的第二条评论澄清了关系,为了兼容性和稳健性,我应尽可能使用WINAPI。 - xaler7
1
而 kernel32!CreateFile 调用 ntdll!NtCreateFile,这是实际的内核系统调用(最终在内核的 IO 管理器部分调用 IoCreateFile)。 - Chris Smith

10

C语言对于GUI完全不了解,对于操作系统也仅仅知之甚少。在C语言中,所有的图形处理都需要通过库来实现,其中win32 api就是一个例子。


5

Windows API是用C编程语言实现的。由C标准库提供的功能,例如fopen,是可移植的,因为它会被不同编译器编译成适合不同架构的汇编代码。Windows API函数,例如CreateFile,仅在运行Windows的机器上工作,因此不具备可移植性。


5
理论上可以编写直接与硬件交互的C代码。例如在MS-DOS时代,由于MS-DOS无法提供我们需要的功能,许多人经常这样做。但现代系统(如Linux和Windows)已经更加完善,因此没有太多必要直接处理硬件。另外,大多数系统现在运行在保护模式下,因此普通用户代码不能直接与硬件交互,必须通过某种设备驱动程序来实现。是的,大多数C库使用底层操作系统,因此在Windows上,fopen和fwrite最终将调用CreateFile和WriteFile,而在Linux上则会调用open和write。

2
我注意到在打开文件的c(库?)版本和Windows API版本(CreateFile)之间存在相似之处。这并不奇怪,它们执行类似的操作。
一个是否只是另一个的包装器?有人知道吗?你无法找出答案,因为源代码是商业机密。哪个更“基本”并不重要。从Windows程序中使用Windows API,从C程序中使用C API。
请注意,这并不重要。您可以混合使用C API或Windows API。
如果Windows正在运行,则某人是否被迫使用Windows API来在其上运行某些内容,还是可以完全绕过Windows直接访问硬件?
“直接访问硬件”是什么意思?如果Windows正在运行,那么...嗯...Windows正在运行。Windows会调解您对硬件的访问。
使用Bootcamp或GRUB或其他引导加载程序绕过Windows并具有“直接访问硬件”的功能。
如果他们能够这样做,如果您不知道自己在做什么,是否可能损坏硬件?
这是什么意思?您是否在询问是否可以通过错误使用其驱动程序来“损坏”一些旋转介质(即磁盘)?无论您运行或未运行任何操作系统,都可以损坏硬盘。特权帐户和愚蠢的软件可以在磁盘上写入错误的数据。这算“损坏”吗?
哪个更具可移植性?
这是什么意思?到另一台运行Windows的计算机?到不运行Windows的计算机?您在问什么?请澄清您的问题,以定义您所说的“可移植性”。
在不同版本的Windows之间
由于不同版本的Windows是互不兼容的,我通常建议仅使用POSIX标准库并避免所有Windows API。然而,某些Windows变体(例如电话的Windows移动版与Windows“服务器”)基本上是完全不兼容的。没有任何软件需要在两个操作系统上运行。可移植性并不重要。为什么要尝试在服务器上运行电话应用程序?
编辑
那么,在底层有c语言(最接近硬件),然后是Windows API,然后是C库放在Windows API之上?
这没有意义。您混淆了两个无关的事情。“语言”和“库”几乎没有任何关系。
此外,API不是操作系统。因此,通过始终使用Windows“API”,您使这更加复杂化了。
以下是一种查看此方法的方式。
  • Windows操作系统有几个API。其中有一些函数库不属于应用程序接口,它们是“内部的”。
  • 它有一个本地的Windows API。可从C语言中调用。
  • 它有一个POSIX API。可从C语言中调用。在某些情况下,Posix API通常使用Windows API。

阅读了您的回复后,我觉得我对可移植性的定义可能有误。请参见顶部关于可移植性的评论。 - xaler7
2
我认为这些源代码不是商业机密。微软将fopen.c与Visual Studio一起发布。 - Ken
我所说的是Dean 'codeka' Harding在上面的第二条评论的重新表述,也许他说得比我更清楚易懂。 - xaler7

1

大多数操作系统,包括Windows,都是用C(和/或汇编语言)编写的。然后为每个操作系统修改库以执行基本操作(套接字、文件、内存等)。

WINAPI只是一堆库(用C和/或汇编语言编写),允许访问操作系统内部的功能。

它与Windows无关,在您更改问题后,我认为您想要了解的是操作系统(Windows或其他操作系统)的引导过程。
操作系统设计与实现这本书讨论了Minix的实现(Linux就是基于它的)。


1

WinAPI 提供了一个接口,C 开发人员可以使用它来使用 WinAPI 功能。C++ 程序也可以使用它。


0

像Windows这样的操作系统包含WINAPI库,提供对某些操作系统功能和硬件的访问,这些库是用C语言编写的。


0

Carl Norum指出,C语言早在Windows之前就存在了,但不要忘记Windows API基本上是从MS-DOS API开始的,而这个API又是从CP/M API开始的。 C语言在CP/M之前只存在了很短的时间。

许多答案似乎暗示Windows API是基于C语言构建的,但这也似乎是值得怀疑的。 __stdcall是PASCAL的同义词,在Microsoft的C编译器中是一个关键字,因为Windows API是基于Pascal构建的。 __cdecl是Visual Studio编译的C和C ++程序中函数调用的默认值,但它无法在调用API时使用。

C语言和Windows API之间的关系是它们能够互相配合工作。


关于Pascal的说法不正确,请阅读Raymond Chen的这篇文章:http://blogs.msdn.com/b/oldnewthing/archive/2004/01/02/47184.aspx#47343 - Amro
Amro说:“关于Pascal的说法不正确,可以看看Raymond Chen的这篇文章:http://blogs.msdn.com/b/oldnewthing/archive/2004/01/02/47184.aspx#47343”。在那篇文章中,我读到了“几乎所有的Win16函数都是按照Pascal调用约定导出的。”但是那篇文章并没有涉及Win32。 - Windows programmer
那篇文章解释了Win16 API最初为什么使用Pascal调用约定(现在Win32使用stdcall约定,是第一种的变体)。关键是,无论是Win16还是Win32,都不是用Pascal编写的,而是混合了汇编和C语言...甚至有迹象表明,未来版本的C运行时库将内部用C++编写:http://blogs.msdn.com/b/vcblog/archive/2014/06/10/the-great-crt-refactoring.aspx - Amro
Amro,请阅读此网页的标题。阅读问题。没有人问过Win16或Win32代码中使用了哪种语言。问题是关于API的。 “API”中的“I”代表“接口”。 - Windows programmer
好的,但是我的评论(和投票)是关于您的陈述,“Windows API是基于Pascal构建的”,这是不正确的。语言和调用约定是两个不同的事情。 - Amro

0
作为一个有趣的提示,您可以通过查看AutoIt(http://www.autoitscript.com/autoit3/)真正了解Windows API的“力量”。 AutoIt是一种非常棒的脚本语言,可以创建GUI、运行命令行应用程序、操作窗口和进程等等。是的,它还可以进行文件I/O和网络通信。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接