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 가지 속성이 있습니다.
- C 및 C ++는 메모리에 액세스 할 수 있습니다
- 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에서 “랩핑 (wrapped)”되므로 직접 처리 할 필요가 없습니다. 그러나 그 아래에는 O / S 관련 리소스와 관련된 모든 작업이 인쇄, 네트워킹 및 소켓 등 시스템 호출을 사용합니다.
Windows의 경우 Microsoft Windows에는 실제로 GUI에 커널이 작성되어 있으므로 창을 작성하거나 그래픽을 그리는 등의 시스템 호출이 있습니다. 다른 운영 체제에서는 GUI가 커널의 일부가 아닐 수 있습니다. 내가 아는 한 GUI 관련 사항에 대한 시스템 호출은 없으며, 낮은 수준의 그래픽 및 입력 관련 호출을 사용할 수 있으면 더 낮은 수준에서만 작업 할 수 있습니다.
답변
좋은 질문. 모든 새로운 C 또는 C ++ 개발자는이를 염두에두고 있습니다. 이 게시물의 나머지 부분에 대해 표준 x86 시스템을 가정합니다. Microsoft C ++ 컴파일러를 사용하는 경우 메모장을 열고 이것을 입력하십시오 (파일 이름은 Test.c).
int main(int argc, char **argv)
{
return 0
}
이제이 파일을 컴파일하십시오 (개발자 명령 프롬프트 사용) cl Test.c /FaTest.asm
메모장에서 Test.asm을 엽니 다. 번역 된 코드는 C / C ++가 어셈블러로 변환 된 것입니다. 힌트가 있습니까?
_main PROC
push ebp
mov ebp, esp
xor eax, eax
pop ebp
ret 0
_main ENDP
C / C ++ 프로그램은 금속에서 실행되도록 설계되었습니다. 즉, 하위 수준의 하드웨어에 액세스 할 수 있으므로 하드웨어 기능을 쉽게 이용할 수 있습니다. x86 컴퓨터에서 C 라이브러리 getch ()를 작성한다고 가정 해보십시오.
어셈블러에 따라 다음과 같이 입력합니다.
_getch proc
xor AH, AH
int 16h
;AL contains the keycode (AX is already there - so just return)
ret
어셈블러를 사용하여 실행하고 .OBJ-getch.obj라는 이름을 생성합니다.
그런 다음 C 프로그램을 작성합니다 (#include 아무것도 포함하지 않습니다)
extern char getch();
void main(int, char **)
{
getch();
}
이제이 파일 이름을 GetChTest.c로 지정하십시오. getch.obj를 전달하여이 파일을 컴파일하십시오. 또는 개별적으로 .obj 및 LINK GetChTest.Obj 및 getch.Obj로 컴파일하여 GetChTest.exe를 생성합니다.
GetChTest.exe를 실행하면 키보드 입력을 기다립니다.
C / C ++ 프로그래밍은 언어에 관한 것이 아닙니다. 우수한 C / C ++ 프로그래머가 되려면 실행되는 머신 유형에 대해 잘 알고 있어야합니다. 메모리 관리가 어떻게 처리되는지, 레지스터가 어떻게 구성되는지 등을 알아야합니다. 정기적 인 프로그래밍을 위해 이러한 정보가 모두 필요한 것은 아닙니다. 기본 하드웨어 지식 외에도 컴파일러가 작동하는 방식 (예 : 변환 방법)을 이해하면 도움이되므로 필요한 경우 코드를 조정할 수 있습니다. 재미있는 패키지입니다!
두 언어 모두 __asm 키워드를 지원하므로 어셈블리 언어 코드도 혼합 할 수 있습니다. C와 C ++를 배우면 전반적으로 더 나은 프로그래머가 될 것입니다.
항상 어셈블러와 연결할 필요는 없습니다. 나는 그것이 당신이 더 잘 이해하는 데 도움이 될 것이라고 생각했기 때문에 언급했습니다. 대부분의 이러한 라이브러리 호출은 운영 체제에서 제공하는 시스템 호출 / API를 사용합니다 (OS는 하드웨어 상호 작용을 수행함).
답변
C ++는 어떻게 C ++ 자체로 작성된 라이브러리를 통해 그러한 기능을 갑자기 얻습니까?
다른 라이브러리를 사용하는 것에 대한 마술은 없습니다. 라이브러리는 호출 할 수있는 단순한 기능의 큰 백입니다.
이와 같은 함수를 작성하는 것을 고려하십시오.
void addExclamation(std::string &str)
{
str.push_back('!');
}
이제 그 파일을 포함 시키면 addExclamation(myVeryOwnString);
. “여러분은 C ++에서 어떻게 문자열에 느낌표를 추가 할 수 있었습니까?” 답은 쉽다 : 당신은 그것을하기위한 함수를 작성한 다음 그것을 호출했다.
따라서 C ++에서 C ++로 작성된 라이브러리를 통해 창을 그리는 기능을 얻는 방법에 대한 질문에 대답하려면 대답은 동일합니다. 다른 누군가가 그렇게하기 위해 함수를 작성한 다음 컴파일하여 라이브러리 형태로 당신에게주었습니다.
다른 질문은 창 그리기가 실제로 어떻게 작동하는지 대답하지만 라이브러리 작동 방식에 대해 혼란스러워서 질문의 가장 근본적인 부분을 다루고 싶었습니다.