IT story

언어는 어떻게 확장됩니까?

hot-time 2020. 5. 1. 08:08
반응형

언어는 어떻게 확장됩니까? [닫은]


C ++을 배우고 있으며 GUI 프로그램을 코딩 하는 Qt 의 기능 중 일부에 대해 배우기 시작했습니다 . 나는 나 자신에게 다음과 같은 질문을했다.

이전에 OS에 창을 요구하거나 네트워크를 통해 통신 할 수있는 방법을 요구할 수있는 구문이 없었던 C ++ (어떻게도 완전히 이해하지 못하는 API로) 은 C ++ 자체로 작성된 라이브러리를 통해 그러한 기능 갑자기 얻는가 ? 그것은 나에게 정말 원형 인 것 같습니다. 해당 라이브러리에서 어떤 C ++ 명령어를 만들 수 있습니까?

이 질문은 숙련 된 소프트웨어 개발자에게는 사소한 것처럼 보이지만 직접 응답을 찾지 않고 몇 시간 동안 연구 해 왔습니다. 라이브러리의 존재가 이해할 수 없기 때문에 Qt에 대한 자습서를 따를 수없는 시점에 도달했습니다.


컴퓨터는 양파와 같습니다. 순수한 하드웨어의 내부 코어에서 최 외곽 응용 계층에 이르기까지 많은 계층이 있습니다. 각각의 층은 그 자체의 일부를 다음 외부 층에 노출 시키므로, 외부 층은 내부 층 기능 중 일부를 사용할 수있다.

예를 들어 Windows의 경우 운영 체제는 Windows에서 실행되는 응용 프로그램에 대해 WIN32 API를 노출합니다. Qt 라이브러리는 해당 API를 사용하여 Qt를 사용하는 애플리케이션을 자체 API에 제공합니다. Qt를 사용하고, Qt는 WIN32를 사용하고, WIN32는 하드웨어의 전기 신호가 될 때까지 낮은 수준의 Windows 운영 체제를 사용합니다.


일반적으로 라이브러리는 아직 불가능한 것을 만들 수 없습니다.

그러나 C ++ 프로그램에서 사용할 수 있도록 라이브러리를 C ++로 작성할 필요는 없습니다. C ++로 작성 되었더라도 내부적으로 C ++로 작성되지 않은 다른 라이브러리를 사용할 수 있습니다. C ++ 너무 오래 존재하는 한,이 추가되는 것을 금지하지 않습니다 할 수있는 방법을 제공하지 않은 사실 그래서 일부 ++ C 외부에서 작업을 수행하는 방법.

상당히 낮은 수준에서 C ++ (또는 C)에 의해 호출 된 일부 함수는 어셈블리로 작성되며, 어셈블리에는 C ++에서 불가능하거나 쉽지 않은 것을 수행하는 데 필요한 명령 (예 : 호출)이 포함됩니다. 시스템 기능. 이 시점에서 시스템 호출은 컴퓨터가 멈추는 것이 없기 때문에 컴퓨터가 할 수있는 모든 작업을 수행 할 수 있습니다.


C 및 C ++에는 OP가 말하는 모든 확장 성을 허용하는 2 가지 속성이 있습니다.

  1. C 및 C ++는 메모리에 액세스 할 수 있습니다
  2. C 및 C ++는 C 또는 C ++ 언어가 아닌 명령어에 대한 어셈블리 코드를 호출 할 수 있습니다.

커널 또는 기본 비보호 모드 플랫폼에서 직렬 포트 또는 디스크 드라이브와 같은 주변 장치는 RAM과 같은 방식으로 메모리 맵에 매핑됩니다. 메모리는 일련의 스위치이며 직렬 포트 나 디스크 드라이버와 같은 주변 장치의 스위치를 뒤집 으면 주변 장치가 유용한 작업을 수행 할 수 있습니다.

보호 모드 운영 체제에서 사용자 공간에서 커널에 액세스하려면 (예 : 파일 시스템에 쓰거나 화면에 픽셀을 그릴 때) 시스템 호출이 필요합니다. C에는 시스템 호출을 지시하는 명령이 없지만 C는 올바른 시스템 호출을 트리거 할 수있는 어셈블러 코드를 호출 할 수 있습니다. 이것이 C 코드가 커널과 통신 할 수있게하는 것입니다.

특정 플랫폼을 쉽게 프로그래밍 할 수 있도록 시스템 호출은보다 복잡한 기능으로 래핑되어 자체 프로그램 내에서 유용한 기능을 수행 할 수 있습니다. 하나는 시스템 호출을 직접 호출 할 수 있지만 (어셈블러 사용) 플랫폼이 제공하는 래퍼 함수 중 하나를 사용하는 것이 더 쉽습니다.

시스템 호출보다 훨씬 유용한 다른 수준의 API가 있습니다. 예를 들어 malloc을 보자. 이를 통해 시스템은 큰 메모리 블록을 확보하기 위해 시스템을 호출 할뿐만 아니라 발생하는 모든 작업을 수행하여이 메모리를 관리합니다.

Win32 API는 일부 그래픽 기능을 공통 플랫폼 위젯 세트로 래핑합니다. Qt는 Win32 (또는 X Windows) API를 크로스 플랫폼 방식으로 래핑하여 이것을 조금 더 발전시킵니다.

기본적으로 C 컴파일러는 C 코드를 기계 코드로 변환하지만 컴퓨터가 기계 코드를 사용하도록 설계되었으므로 C가 라이온스 공유 또는 컴퓨터로 수행 할 수있는 작업을 수행 할 수있을 것으로 기대해야합니다. 랩퍼 라이브러리가하는 모든 작업은 사용자를 위해 무거운 물건을 들기 만하면됩니다.


언어 (예 : C ++ 11 )는 일반적으로 영어로 작성된 용지의 사양 입니다. 최신 C ++ 11 초안을 살펴보십시오 (또는 ISO 공급 업체로부터 값 비싼 최종 사양구매하십시오 ).

일반적으로 언어가 구현 된 컴퓨터를 사용합니다 (원칙적으로 컴퓨터를 해석하지 않고 C ++ 프로그램을 실행할 수 있습니다 (예 : 많은 인간 노예를 사용하여 해석하는 경우 비 윤리적이고 비효율적 임)).

C ++ 구현 일반은 일부 운영 체제 이상에서 작동하며 ( 일부 시스템 라이브러리에서 일부 구현 특정 코드를 사용하여) 통신합니다 . 일반적으로 통신은 시스템 호출을 통해 수행됩니다 . 로 예를 들어 봐 콜 (2) 시스템의 목록은 볼 수 호출 리눅스 커널 .

응용 프로그램 관점에서 syscall은 SYSENTER일부 규칙 ( ABI )이있는 x86-64와 같은 기본 기계 명령어입니다.

내 Linux 데스크탑에서 Qt 라이브러리는 X Windows 서버를 통해 X11 서버 Xorg 와 통신하는 X11 클라이언트 라이브러리 위에 있습니다 .

Linux에서 ldd실행 파일을 사용 하여 라이브러리에 대한 (긴) 종속성 목록을보십시오. 사용 pmap하여 실행중인 프로세스에이 사람이 런타임에 "로드"되는 볼 수 있습니다. BTW, Linux에서 응용 프로그램은 무료 소프트웨어 만 사용하고 있으며 소스 코드 (Qt에서 Xlib, libc, ... 커널까지)를 연구하여 발생하는 일을 더 많이 이해할 수 있습니다.


당신이 빠진 개념은 시스템 호출 이라고 생각 합니다 . 각 운영 체제는 저수준 운영 체제 관련 작업을 수행하기 위해 활용할 수있는 엄청난 양의 리소스와 기능을 제공합니다. 일반 라이브러리 함수를 호출하더라도 장면 뒤에서 시스템 호출이 발생했을 수 있습니다.

시스템 호출은 운영 체제의 강력한 기능을 사용하는 저수준 방법이지만 사용하기가 복잡하고 번거로울 수 있으므로 API에서 "랩핑"되어 직접 처리 할 필요가없는 경우가 많습니다. 그러나 그 아래에는 O / S 관련 리소스와 관련된 모든 작업이 인쇄, 네트워킹 및 소켓 등 시스템 호출을 사용합니다.

Windows의 경우 Microsoft Windows에는 실제로 GUI에 커널이 작성되어 있으므로 창을 작성하거나 그래픽을 그리는 등의 시스템 호출이 있습니다. 다른 운영 체제에서는 GUI가 커널의 일부가 아닐 수 있습니다. 내가 아는 한 GUI 관련 사항에 대한 시스템 호출은 없으며, 저수준 그래픽 및 입력 관련 호출이 가능한 경우에는 훨씬 낮은 수준에서만 작업 할 수 있습니다.


Good question. Every new C or C++ developer has this in mind. I am assuming a standard x86 machine for the rest of this post. If you are using Microsoft C++ compiler, open your notepad and type this (name the file Test.c)

int main(int argc, char **argv)
{
   return 0
}

And now compile this file (using developer command prompt) cl Test.c /FaTest.asm

Now open Test.asm in your notepad. What you see is the translated code - C/C++ is translated to assembler. Do you get the hint ?

_main   PROC
    push    ebp
    mov ebp, esp
    xor eax, eax
    pop ebp
    ret 0
_main   ENDP

C/C++ programs are designed to run on the metal. Which means they have access to lower level hardware which makes it easier to exploit the capabilities of the hardware. Say, I am going to write a C library getch() on a x86 machine.

Depending on the assembler I would type something this way :

_getch proc 
   xor AH, AH
   int 16h
   ;AL contains the keycode (AX is already there - so just return)
ret

I run it over with an assembler and generate a .OBJ - Name it getch.obj.

I then write a C program (I dont #include anything)

extern char getch();

void main(int, char **)
{
  getch();
}

Now name this file - GetChTest.c. Compile this file by passing getch.obj along. (Or compile individually to .obj and LINK GetChTest.Obj and getch.Obj together to produce GetChTest.exe).

Run GetChTest.exe and you would find that it waits for the keyboard input.

C/C++ programming is not just about language. To be a good C/C++ programmer you need to have a good understanding on the type of machine that it runs. You will need to know how the memory management is handled, how the registers are structured, etc., You may not need all these information for regular programming - but they would help you immensely. Apart from the basic hardware knowledge, it certainly helps if you understand how the compiler works (ie., how it translates) - which could enable you to tweak your code as necessary. It is an interesting package!

Both languages support __asm keyword which means you could mix your assembly language code too. Learning C and C++ will make you a better rounded programmer overall.

It is not necessary to always link with Assembler. I had mentioned it because I thought that would help you understand better. Mostly, most such library calls make use of system calls / APIs provided by the Operating System (the OS in turn does the hardware interaction stuff).


How does C++ ... suddenly get such capabilities through libraries written in C++ themselves ?

There's nothing magical about using other libraries. Libraries are simple big bags of functions that you can call.

Consider yourself writing a function like this

void addExclamation(std::string &str)
{
    str.push_back('!');
}

Now if you include that file you can write addExclamation(myVeryOwnString);. Now you might ask, "how did C++ suddenly get the capability to add exclamation points to a string?" The answer is easy: you wrote a function to do that then you called it.

So to answer your question about how C++ can get capabilities to draw windows through libraries written in C++, the answer is the same. Someone else wrote function(s) to do that, and then compiled them and gave them to you in the form of a library.

The other questions answer how the window drawing actually works, but you sounded confused about how libraries work so I wanted to address the most fundamental part of your question.


The key is the possibility of the operating system to expose an API and a detailed description on how this API is to be used.

The operating system offers a set of APIs with calling conventions. The calling convention is defining the way a parameter is given into the API and how results are returned and how to execute the actual call.

Operating systems and the compilers creating code for them play nicely together, so you usually have not to think about it, just use it.


There is no need for a special syntax for creating windows. All that is required is that the OS provides an API to create windows. Such an API consists of simple function calls for which C++ does provide syntax.

Furthermore C and C++ are so called systems programming languages and are able to access arbitrary pointers (which might be mapped to some device by the hardware). Additionally, it is also fairly simple to call functions defined in assembly, which allows the full range of operations the processor provides. Therefore it is possible to write an OS itself using C or C++ and a small amount of assembly.

It should also be mentioned that Qt is a bad example, as it uses a so-called meta compiler to extend C++' syntax. This is however not related to it's ability to call into the APIs provided by the OS to actually draw or create windows.


First, there's a little misunderstading, I think

How does C++, which previously had no syntax capable of asking the OS for a window or a way to communicate through networks

There is no syntax for doing OS operations. It's the question of semantics.

suddenly get such capabilities through libraries written in C++ themselves

Well, the operating system is writen mostly in C. You can use shared libraries (so, dll) to call the external code. Additionally, the operating system code can register system routines on syscalls* or interrupts which you can call using assembly. That shared libraries often just make that system calls for you, so you are spared using inline assembly.

Here's the nice tutorial on that: http://www.win.tue.nl/~aeb/linux/lk/lk-4.html
It's for Linux, but the principles are the same.

How the operating system is doing operations on graphic cards, network cards etc? It's a very broad thema, but mostly you need to access interrupts, ports or write some data to special memory region. Since that operations are protected, you need to call them through the operating system anyway.


In an attempt to provide a slightly different view to other answers, I shall answer like this.

(Disclaimer: I am simplifying things slightly, the situation I give is purely hypothetical and is written as a means of demonstrating concepts rather than being 100% true to life).

Think of things from the other perspective, imagine you've just written a simple operating system with basic threading, windowing and memory management capabilities. You want to implement a C++ library to let users program in C++ and do things like make windows, draw onto windows etc. The question is, how to do this.

Firstly, since C++ compiles to machine code, you need to define a way to use machine code to interface with C++. This is where functions come in, functions accept arguments and give return values, thus they provide a standard way of transferring data between different sections of code. They do this by establishing something known as a calling convention.

A calling convention states where and how arguments should be placed in memory so that a function can find them when it gets executed. When a function gets called, the calling function places the arguments in memory and then asks the CPU to jump over to the other function, where it does what it does before jumping back to where it was called from. This means that the code being called can be absolutely anything and it will not change how the function is called. In this case however, the code behind the function would be relevant to the operating system and would operate on the operating system's internal state.

So, many months later and you've got all your OS functions sorted out. Your user can call functions to create windows and draw onto them, they can make threads and all sorts of wonderful things. Here's the problem though, your OS's functions are going to be different to Linux's functions or Windows' functions. So you decide you need to give the user a standard interface so they can write portable code. Here is where QT comes in.

As you almost certainly know, QT has loads of useful classes and functions for doing the sorts of things that operating systems do, but in a way that appears independent of the underlying operating system. The way this works is that QT provides classes and functions that are uniform in the way they appear to the user, but the code behind the functions is different for each operating system. For example QT's QApplication::closeAllWindows() would actually be calling each operating system's specialised window closing function depending on the version used. In Windows it would most likely call CloseWindow(hwnd) whereas on an os using the X Window System, it would potentially call XDestroyWindow(display,window).

As is evident, an operating system has many layers, all of which have to interact through interfaces of many varieties. There are many aspects I haven't even touched on, but to explain them all would take a very long time. If you are further interested in the inner workings of operating systems, I recommend checking out the OS dev wiki.

Bear in mind though that the reason many operating systems choose to expose interfaces to C/C++ is that they compile to machine code, they allow assembly instructions to be mixed in with their own code and they provide a great degree of freedom to the programmer.

Again, there is a lot going on here. I would like to go on to explain how libraries like .so and .dll files do not have to be written in C/C++ and can be written in assembly or other languages, but I feel that if I add any more I might as well write an entire article, and as much as I'd love to do that I don't have a site to host it on.


When you try to draw something on the screen, your code calls some other piece of code which calls some other code (etc.) until finally there is a "system call", which is a special instruction that the CPU can execute. These instructions can be either written in assembly or can be written in C++ if the compiler supports their "intrinsics" (which are functions that the compiler handles "specially" by converting them into special code that the CPU can understand). Their job is to tell the operating system to do something.

When a system call happens, a function gets called that calls another function (etc.) until finally the display driver is told to draw something on the screen. At that point, the display driver looks at a particular region in physical memory which is actually not memory, but rather an address range that can be written to as if it were memory. Instead, however, writing to that address range causes the graphics hardware to intercept the memory write, and draw something on the screen.
Writing to this region of memory is something that could be coded in C++, since on the software side it's just a regular memory access. It's just that the hardware handles it differently.
So that's a really basic explanation of how it can work.


Your C++ program is using Qt library (also coded in C++). The Qt library will be using Windows CreateWindowEx function (which was coded in C inside kernel32.dll). Or under Linux it may be using Xlib (also coded in C), but it could as well be sending the raw bytes that in X protocol mean "Please create a window for me".

Related to your catch-22 question is the historical note that “the first C++ compiler was written in C++”, although actually it was a C compiler with a few C++ notions, enough so it could compile the first version, which could then compile itself.

Similarly, the GCC compiler uses GCC extensions: it is first compiled to a version then used to recompile itself. (GCC build instructions)


How i see the question this is actually a compiler question.

Look at it this way, you write a piece of code in Assembly(you can do it in any language) which translates your newly written language you want to call Z++ into Assembly, for simplicity lets call it a compiler (it is a compiler).

Now you give this compiler some basic functions, so that you can write int, string, arrays etc. actually you give it enough abilities so that you can write the compiler itself in Z++. and now you have a compiler for Z++ written in Z++, pretty neat right.

Whats even cooler is that now you can add abilities to that compiler using the abilities it already has, thus expanding the Z++ language with new features by using the previous features

An example, if you write enough code to draw a pixel in any color, then you can expand it using the Z++ to draw anything you want.


The hardware is what allows this to happen. You can think of the graphics memory as a large array (consisting of every pixel on the screen). To draw to the screen you can write to this memory using C++ or any language that allows direct access to that memory. That memory just happens to be accessible by or located on the graphics card.

On modern systems accessing the graphics memory directly would require writing a driver because of various restrictions so you use indirect means. Libraries that create a window (really just an image like any other image) and then write that image to the graphics memory which the GPU then displays on screen. Nothing has to be added to the language except the ability to write to specific memory locations, which is what pointers are for.

참고URL : https://stackoverflow.com/questions/24993282/how-does-a-language-expand-itself

반응형