Як мова розширюється сама? [зачинено]


208

Я вивчаю C ++, і я щойно почав дізнаватися про деякі можливості Qt для кодування програм GUI. Я задав собі таке питання:

Як C ++, у якого раніше не було синтаксису, здатного запитувати ОС для вікна або способу спілкування через мережі (з API, які я також не повністю розумію, я визнаю) раптом отримує такі можливості через бібліотеки, написані в C ++ самі? Це мені здається страшенно круглим. Які інструкції на C ++ ви могли б запропонувати в цих бібліотеках?

Я усвідомлюю, що це питання може здатися тривалим для досвідченого розробника програмного забезпечення, але я займався дослідженнями годинами, не знаходячи прямої відповіді. Дійшло до того, що я не можу дотримуватися підручника про Qt, оскільки існування бібліотек для мене незрозуміле.


27
Як std :: cout навіть малює що-небудь на моніторі? Або він сидить зверху на компіляторі, який розуміє ваше обладнання?
doctorlove

14
Чудове запитання. Зрештою, важко відповісти, поки ви не вивчите обладнання.
користувач541686

17
Qt не є розширенням мови (для цього потрібен компілятор, обізнаний із Qt). Це просто бібліотека, яка додана до вашого арсеналу. Врешті-решт, на найнижчому рівні всі бібліотеки спілкуються з ОС за допомогою системних викликів, які не залежать від мови, але дуже залежать від ОС та архітектури процесора.
DevSolar

8
afaik, у C ++ є вбудована збірка, яка може зробити майже все
Відображати ім'я

9
@DevSolar: Насправді Qt дійсно розширює мову за допомогою власного механізму сигнального слота, відображення та багатьох інших динамічних особливостей. І для цих речей потрібен компілятор (компілятор мета-об’єктів) для компіляції до коду C ++.
Сіюань Рен

Відповіді:


194

Комп'ютер схожий на цибулю, він має багато багато шарів, від внутрішнього ядра чистого обладнання до самого зовнішнього шару програми. Кожен шар піддає частини себе наступному зовнішньому шару, так що зовнішній шар може використовувати деяку функціональність внутрішніх шарів.

У випадку, наприклад, Windows, операційна система виставляє так званий API WIN32 для програм, що працюють під управлінням Windows. Бібліотека Qt використовує цей API для надання додатків, що використовують Qt, для власного API. Ви використовуєте Qt, Qt використовує WIN32, WIN32 використовує нижчі рівні операційної системи Windows і так далі, поки в апараті не з’являються електричні сигнали.


56
Примітка: Qtтут передбачено абстрагування шару під ним, оскільки в Linux Qtвизывается API Linux, а не API WIN32.
Матьє М.

5
Напевно, я б трохи більше розробив на прикладі Qt, що він просто з'являється, як би він без особливих зусиль розширює можливості c ++. Коли реальність є, вони докладають чимало зусиль, щоб зробити спільний API, щоб (спірним чином) було багато різних "луків цибулі". Саме вони забезпечують переносність поверх не портативних нестандартних програмних засобів.
luk32

81
Комп’ютер - це як цибуля: прорізавши його, ви плачете, але згодом це дещо смачно.
alecov

3
@ChristopherPfohl Так, мені довелося його використовувати, оскільки я не міг зрозуміти, яким буде комп’ютер, як коробка цукерок. :)
Якийсь програміст чувак

1
@Celeritas, напевно, сказав учитель user32.dll, чи можливо gdi32.dll.
користувач253751

59

Ви праві, що в цілому бібліотеки не можуть зробити все можливим, що вже не можливо.

Але бібліотеки не повинні записуватися на C ++, щоб користуватися програмою C ++. Навіть якщо вони написані на C ++, вони можуть внутрішньо використовувати інші бібліотеки, які не написані на C ++. Тому той факт , що C ++ не передбачає будь - який спосіб зробити це не заважає йому бути додані до тих пір, поки існує якийсь - то спосіб зробити це за межами C ++.

На досить низькому рівні деякі функції, викликані C ++ (або C), будуть записані в збірку, і збірка містить необхідні вказівки робити все, що неможливо (або це не просто) в C ++, наприклад, для виклику системна функція. У цей момент цей системний виклик може робити все, на що ваш комп'ютер здатний, просто тому, що нічого не зупиняє його.


Ви маєте на увазі, що бібліотеки, написані іншими мовами, зібрані вже за допомогою інших компіляторів? І тоді мав би бути якийсь файл інтерфейсу, що пов'язує кожен виклик функції, що надається бібліотекою C ++, до попередньо складеної версії бібліотеки? Таким чином, дозволяючи компілятору C ++ знати, що перекласти ці виклики?
Med Larbi Sentissi

2
@MedLarbiSentissi 1) Не обов'язково інші компілятори. Можливо (і часто трапляється так), що один компілятор здатний компілювати декілька мов, включаючи збірку, і навіть може бути здатний компілювати C ++ з вбудованою збіркою. 2) Залежно від конкретної системи та компілятора, перетворення цих функцій на C ++ може дійсно виконуватися за допомогою якогось файлу інтерфейсу, але такий файл інтерфейсу вже може бути заголовком C (або навіть C ++), безпосередньо використовуваним із C ++.

1
@MedLarbiSentissi: Багато бібліотек Windows збираються у файли dll, які містять власний інтерфейс, а також код. Ви можете зазирнути в dll і переглянути список функцій, які він дозволяє використовувати. Вони часто також поставляються з файлом заголовка C. Коли ви створюєте свій exe, він містить список DLL, який він повинен працювати. Коли ОС намагається завантажити ваш exe, вона також автоматично завантажить ці dll перед початком виконання.
Mooing Duck

8
Ця відповідь, схоже, говорить про те, що "магія" повністю полягає в інших названих мовах, але насправді більша частина коду, який складається з більшості сучасних операційних систем, - це C (з монтажем написані лише дуже прив'язані до апаратури або критичні для продуктивності частини) - і це , безумовно , можна використовувати C ++ замість цього. Справа в тому, що немає ніякої "магії", мови створюються для створення таких потужних абстракцій, і коли ви можете взаємодіяти з обладнанням, можливості майже безмежні.
Маттео Італія

1
@hvd Я думаю, що весь конфлікт у цій дискусії полягає в тому, що ви (та інші) визначаєте C як визначені для нього функції. Насправді, компілятори додають набагато більше, ніж зазначено, що робить питання про те, що C начебто нетривіально відповідати. Для мене особлива річ у мові (таким чином, річ, яка вона є) - мета-спосіб експресії потоку програми та можливості структурування. Структуровані елементи для нього неважливі, оскільки це лише приємніший ASM-код, який компілятори можуть додавати за своїм бажанням
LionC

43

C і C ++ мають 2 властивості, які дозволяють усю цю розширюваність, про яку йдеться в ОП.

  1. C і C ++ можуть отримати доступ до пам'яті
  2. C і C ++ можуть зателефонувати на збірний код, щоб отримати інструкції не на мові C або C ++.

У ядрі або в базовій незахищеній платформі режиму периферійні пристрої, такі як послідовний порт або дисковий накопичувач, відображаються в карту пам'яті так само, як і в оперативній пам'яті. Пам'ять - це серія комутаторів, і перевертаючи перемикачі периферійного пристрою (наприклад, послідовний порт або драйвер диска), ви отримуєте периферійну мережу для корисних дій.

В операційній системі з захищеним режимом, коли хочеться отримати доступ до ядра з простору користувачів (скажімо, під час запису до файлової системи або для малювання пікселя на екрані), потрібно здійснити системний виклик. C не має інструкції здійснювати системні виклики, але C може викликати код асемблера, який може викликати правильний системний виклик. Це те, що дозволяє коду C спілкуватися з ядром.

Для того, щоб спростити програмування певної платформи, системні виклики обгортаються більш складними функціями, які можуть виконувати якусь корисну функцію у власній програмі. Можна безкоштовно зателефонувати на системні дзвінки (за допомогою асемблера), але, мабуть, простіше просто скористатися однією з функцій обгортки, яку надає платформа.

Є ще один рівень API, який набагато корисніший, ніж системний виклик. Візьмемо для прикладу malloc. Це не тільки зателефонує системі, щоб отримати великі блоки пам'яті, але й буде керувати цією пам’яттю, виконуючи всю книгу про те, що відбувається.

API Win32 містять графічну функціональність за допомогою спільного набору віджетів платформи. Qt робить це трохи далі, обертаючи API Win32 (або X Windows) крос-платформним способом.

По суті, хоча компілятор C перетворює код C у машинний код, і оскільки комп'ютер призначений для використання машинного коду, ви повинні сподіватися, що C зможе виконати частку левів або те, що може зробити комп'ютер. Все, що роблять бібліотеки обгортки, - це зробити важкий підйом для вас, щоб вам не довелося.


Приблизно № 2: C і C ++ можуть лише викликати функції, які дотримуються "конвенції про дзвінки", яку компілятор розуміє та очікує. (Код складання може використовувати будь-яку конвенцію, яка їй подобається, або навіть взагалі жодну - тому код може бути не закликати безпосередньо.) На щастя, кожен поважаючий себе компілятор забезпечує вбудований спосіб використання загальних умов платформи. (Наприклад, компілятори Windows C дозволяють вам / використовувати функції, що використовують умови "cdecl", "stdcall" або "fastcall".) Але код складання повинен використовувати умову, про яку знає компілятор, або C і C ++ можуть ' t називати це безпосередньо.
cHao

2
Також: введення / виведення на карті пам'яті є загальним, але не у всій історії. Наприклад, ПК, як правило, звертаються до послідовних портів, дисководів тощо, використовуючи x86 "порти вводу / виводу", зовсім інший механізм. (
Відеобуфер

@cHao: Звичайно, класичний підхід із використанням INP та OUTP виходить на користь DMA; Здається, покоління PCI більше справляється з картами спеціальних функцій, відображеними на пам'ять, тепер існує спосіб автоматичного зіставлення пристроїв у неперекриваються регіони та виявлення їх у драйверах, а менше - з портами вводу / виводу.
Бен Войгт

сучасні периферійні пристрої використовуватимуть DMA для масової передачі даних, але ви все одно запрограмуєте контролер DMA з адресною пам’яттю
doron

@doron: Umm, ви програмуєте контролер DMA через адресний простір вводу / виводу (а не простір пам'яті) на ПК, принаймні, якщо ви здорові. Сучасні процесори x86 люблять перевпорядковувати доступ до пам'яті для підвищення продуктивності. Що стосується MMIO, це може бути катастрофічним ... тому вам потрібно бути обережними, щоб зробити ці адреси uncacheabke і розмістити інструкції щодо серіалізації у всіх потрібних місцях. Щодо OTOH, x86 сам забезпечує, що читання та запис у просторі вводу / виводу виконуються у програмному порядку. Ось чому значна частина важливих речей все ще робиться через простір вводу-виводу (який, як правило, недоступний за допомогою вказівника), і, ймовірно, завжди буде.
cHao

23

Мови (як C ++ 11 ) - це специфікації на папері, як правило, написані англійською мовою. Загляньте в останню версію C ++ 11 (або придбайте дорогу кінцеву специфікацію у свого постачальника ISO).

Ви, як правило, використовуєте комп’ютер з якоюсь мовною реалізацією (в принципі ви можете запустити програму C ++ без жодного комп’ютера, наприклад, використовуючи купу людських рабів, що їх інтерпретують; це було б неетично і неефективно)

Загальна реалізація C ++ працює над деякою операційною системою і спілкується з нею (використовуючи певний код реалізації , часто в якійсь системній бібліотеці). Як правило, спілкування здійснюється через системні дзвінки . Шукайте, наприклад, у syscalls (2) список системних викликів, доступних у ядрі Linux .

З точки зору програми, syscall - це елементарна машинна інструкція, як SYSENTERна x86-64 з деякими умовами ( ABI )

На моєму робочому столі Linux бібліотеки Qt розташовані вище клієнтських бібліотек X11, які спілкуються з сервером X11 Xorg через протоколи X Windows .

В Linux використовуйте lddу своєму виконуваному файлі, щоб переглянути (довгий) список залежностей від бібліотек. Використовуйте pmapв процесі запуску, щоб побачити, які з них "завантажуються" під час виконання. BTW, в Linux ваша програма, ймовірно, використовує лише вільне програмне забезпечення, ви можете вивчити його вихідний код (від Qt, Xlib, libc, ... ядро), щоб зрозуміти, що відбувається


2
Для довідки, ANSI продає специфікацію C ++ 11 за дещо менш кричущу ціну 60 доларів США. (Раніше це було наполовину, але інфляція.: P) Це позначено як INCITS / ISO / IEC 14882, але це принаймні ті ж базові характеристики, які пропонує ISO. Не впевнений у Errata / TRs.
cHao

19

Я думаю, що концепція, яку вам не вистачає, - це системні дзвінки . Кожна операційна система забезпечує величезну кількість ресурсів та функціональних можливостей, до яких ви можете скористатися, щоб робити речі, пов'язані з низьким рівнем операційної системи. Навіть коли ви викликаєте звичайну функцію бібліотеки, вона, ймовірно, здійснює системний виклик за кадром.

Системні дзвінки - це низький рівень використання потужності операційної системи, але може бути складним і громіздким у використанні, тому їх часто "загортають" в API, так що вам не доведеться з ними безпосередньо працювати. Але під цим, майже все, що ви робите, що стосується ресурсів, пов’язаних з виводуми / перевезеннями, використовуватиме системні дзвінки, включаючи друк, мережу та сокети тощо.

Що стосується Windows, то Microsoft Windows має свій графічний інтерфейс, фактично записаний у ядро, тому існують системні виклики для створення вікон, малювання графіки тощо. В інших операційних системах графічний інтерфейс може не входити до складу ядра, в цьому випадку наскільки я знаю, не було б жодних системних дзвінків для речей, пов’язаних із графічним інтерфейсом, і ви могли працювати лише на ще нижчому рівні, якщо доступні графіки низького рівня та дзвінки, пов'язані з входом.


3
Важливого, чого не вистачає, є те, що ці системні дзвінки аж ніяк не магічні. Їх обслуговує ядро, яке, як правило, записується на С (++). Більше того, систематичні дзвінки навіть не потрібні. У рудиментарній ОС без захисту пам’яті вікна можна намалювати, помістивши пікселі безпосередньо в апаратний фреймбуфер.
el.pescado

15

Гарне питання. Кожен новий розробник 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 ++ розроблені для роботи на металі. Це означає, що вони мають доступ до апаратних засобів нижчого рівня, що полегшує використання можливостей обладнання. Скажімо, я збираюся написати getch () бібліотеки C на машині x86.

Залежно від асемблера, я би ввів щось так:

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

Я запускаю його за допомогою асемблера і генерую .OBJ - Назвіть його getch.obj.

Потім я пишу програму C (я нічого не включаю)

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, що надаються Операційною системою (ОС, у свою чергу, виконує апаратну взаємодію).


10

Як C ++ ... раптом отримує такі можливості через самі бібліотеки, написані на C ++?

Немає нічого магічного у використанні інших бібліотек. Бібліотеки - це прості великі сумки функцій, які ви можете зателефонувати.

Подумайте, як написати таку функцію

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

Тепер, якщо ви включите цей файл, ви можете написати addExclamation(myVeryOwnString);. Тепер ви можете запитати: "як C ++ раптом отримав можливість додавати знаки оклику до рядка?" Відповідь проста: ви написали функцію, щоб це зробити, потім ви її зателефонували.

Отже, щоб відповісти на ваше запитання про те, як C ++ може отримати можливості малювати вікна через бібліотеки, написані на C ++, відповідь однакова. Хтось ще написав функції (и) для цього, а потім склав їх і передав вам у формі бібліотеки.

Інші запитання відповідають на те, як насправді працює малюнок вікон, але ви звучали розгублено щодо того, як працюють бібліотеки, тому я хотів вирішити найбільш фундаментальну частину вашого питання.


8

Ключовим моментом є можливість операційної системи відкрити API і детальний опис того, як цей API повинен використовуватися.

Операційна система пропонує набір API з умовами виклику. Конвенція про виклик визначає спосіб введення параметра в API та те, як повертаються результати та як виконувати фактичний виклик.

Операційні системи та компілятори, що створюють для них код, грають чудово разом, тому зазвичай вам не доводиться думати про це, просто використовуйте його.


7

Для створення вікон не потрібен спеціальний синтаксис. Все, що потрібно, це те, що ОС надає API для створення вікон. Такий API складається з простих функціональних викликів, для яких C ++ надає синтаксис.

Крім того, C і C ++ - це так звані мови програмування систем і мають доступ до довільних покажчиків (які можуть бути відображені апаратними засобами). Крім того, також досить просто викликати функції, визначені в зборі, що дозволяє весь спектр операцій, які забезпечує процесор. Тому можна самостійно написати ОС, використовуючи C або C ++ і невелику кількість збірки.

Слід також зазначити, що Qt є поганим прикладом, оскільки для розширення синтаксису C ++ використовується так званий мета-компілятор . Однак це не пов'язане з його можливістю запускати API, надані ОС для фактичного малювання або створення вікон.


7

По-перше, є невелике непорозуміння, я думаю

Як працює C ++, який раніше не мав синтаксису, здатного запитувати ОС для вікна чи способу спілкування через мережі

Немає синтаксису для операцій з ОС. Це питання семантики .

раптом отримуйте такі можливості через бібліотеки, написані в C ++ самі

Ну, операційна система написана здебільшого на C. Ви можете використовувати спільні бібліотеки (так, dll) для виклику зовнішнього коду. Крім того, код операційної системи може реєструвати підпрограми системи на системних дзвінках * або переривати, які ви можете викликати за допомогою збирання . Ці бібліотеки, що надаються в спільний доступ, часто проводять лише те, що системні дзвінки вам потрібні, тож ви пошкодуєте за допомогою вбудованої збірки.

Ось приємний підручник з цього питання: http://www.win.tue.nl/~aeb/linux/lk/lk-4.html
Це для Linux, але принципи ті самі.

Як операційна система виконує операції з графічними картками, мережевими картками тощо? Це дуже широка тема, але в основному вам потрібно отримати доступ до переривань, портів або записати деякі дані в спеціальну область пам'яті. Оскільки ці операції захищені, вам все одно потрібно викликати їх через операційну систему.


7

Намагаючись дати трохи інший погляд на інші відповіді, я відповім так.

(Відмова: Я трохи спрощую речі, ситуація, яку я даю, суто гіпотетична і написана як засіб демонстрації концепцій, а не 100% вірна життя).

Подумайте про речі з іншої точки зору, уявіть, що ви щойно написали просту операційну систему з основними можливостями управління потоками, вікнами та пам’яттю. Ви хочете впровадити бібліотеку C ++, щоб користувачі могли програмувати на C ++ і робити такі речі, як робити вікна, малювати вікна тощо. Питання полягає в тому, як це зробити.

По-перше, оскільки C ++ компілюється в машинний код, вам потрібно визначити спосіб використання машинного коду для взаємодії з C ++. Ось тут входять функції, функції приймають аргументи і повертають значення, таким чином вони забезпечують стандартний спосіб передачі даних між різними розділами коду. Вони роблять це, встановлюючи щось відоме як закликаюча конвенція .

А угоду про виклики держави , де і як аргументи повинні бути розміщені в пам'яті , так що функція може знайти їх , коли він запускається на виконання. Коли функція викликається, функція виклику розміщує аргументи в пам'яті, а потім просить процесор перейти до іншої функції, де він робить те, що робить, перш ніж перескакувати туди, звідки її викликали. Це означає, що викликаний код може бути абсолютно будь-яким, і він не змінить спосіб виклику функції. Однак у цьому випадку код, який стоїть за цією функцією, буде мати значення для операційної системи і діятиме на внутрішньому стані операційної системи.

Отже, через багато місяців у вас все функції ОС впорядковано. Ваш користувач може викликати функції для створення вікон та малювання на них, вони можуть створювати нитки та всілякі чудові речі. Ось проблема, проте функції вашої ОС будуть відрізнятися від функцій Linux або Windows. Тож ви вирішили потрібно надати користувачеві стандартний інтерфейс, щоб він міг писати портативний код. Ось де QT заходить.

Як ви майже напевно знаєте, QT має безліч корисних класів та функцій для виконання тих чи інших речей, які роблять операційні системи, але таким чином, що вони не залежать від основної операційної системи. Це працює таким чином, що QT надає класи та функції, які є однаковими за способом їх відображення користувачеві, але код за функціями відрізняється для кожної операційної системи. Наприклад, QApplication :: closeAllWindows () QT насправді викликає спеціалізовану функцію закриття вікон кожної операційної системи залежно від використовуваної версії. У Windows він, швидше за все, викликає CloseWindow (hwnd), тоді як на ОС, що використовує X Window System, він потенційно може викликати XDestroyWindow (дисплей, вікно).

Як очевидно, в операційній системі є багато шарів, всі вони повинні взаємодіяти через інтерфейси багатьох різновидів. Є багато аспектів, яких я навіть не торкався, але для їх пояснення потрібно було б дуже багато часу. Якщо вас більше цікавить внутрішня робота операційних систем, я рекомендую перевірити вікі OS dev .

Майте на увазі, що причиною того, що багато операційні системи вирішують виставляти інтерфейси на C / C ++, це те, що вони компілюються в машинний код, вони дозволяють змішувати інструкції зі збирання з власним кодом, і вони надають програмісту велику свободу.

Знову ж таки тут багато чого відбувається. Я хотів би продовжити пояснення, як бібліотеки, такі як .so та .dll файли, не повинні писатись на C / C ++ і можуть бути записані в зборах чи іншими мовами, але я відчуваю, що якщо я ще додаю, я можу також написати всю статтю, і скільки б я хотів зробити це, у мене немає сайту, де можна розмістити її.


6

Коли ви намагаєтеся щось намалювати на екрані, ваш код викликає якийсь інший фрагмент коду, який викликає якийсь інший код (тощо), поки нарешті не з’явиться «системний виклик», що є спеціальною інструкцією, яку може виконати ЦП. Ці вказівки можуть бути або записані в збірку, або можуть бути написані на C ++, якщо компілятор підтримує їх "внутрішні елементи" (це функції, які компілятор обробляє "спеціально", перетворюючи їх у спеціальний код, який може зрозуміти процесор). Їх робота - сказати операційній системі щось робити.

Коли відбувається системний виклик, викликається функція, яка викликає іншу функцію (тощо), поки нарешті драйверу дисплея не наказано щось намалювати на екрані. У цей момент драйвер дисплея дивиться на певну область фізичної пам'яті, яка насправді не є пам'яттю, а скоріше діапазоном адрес, який може бути записаний так, ніби це пам'ять. Натомість, якщо записати на цей діапазон адрес, графічне обладнання перехопить запис пам'яті та щось намалює на екрані.
Запис у цю область пам’яті - це те, що можна закодувати в C ++, оскільки з боку програмного забезпечення це лише звичайний доступ до пам'яті. Просто апаратура обробляє це по-різному.
Тож це дійсно основне пояснення того, як це може працювати.


4
Afaik systemcall насправді не є інструкцією для процесора і не має нічого спільного з внутрішніми характеристиками. Це більше функція ядра операційної системи, яка спілкується з пристроями.
MatthiasB

3
@MatthiasB: Ну, ви помиляєтесь, оскільки syscall(і його двоюрідний брат sysenter) - це дійсно інструкція щодо процесора.
користувач541686

2
Це був лише натяк на покращення вашої відповіді, так як для мене це було не ясно. Не сприймайте це як особисту атаку чи щось подібне.
MatthiasB

1
@MatthiasB: Я не приймаю це особисто. Я кажу, що я вже знаю, що відповідь насправді не є 100% точною, але я думаю, що це досить хороше спрощення, щоб відповісти на ОП - так що, якщо ви насправді знаєте спосіб написати кращу відповідь, то будь ласка, напишіть свою власну відповідь або знайдіть час, щоб відредагувати мою. Я дійсно не маю нічого додати, що, на мою думку, варто цього, тому якщо ви хочете побачити щось краще на цій сторінці, вам доведеться докласти зусиль самостійно.
користувач541686

3
Системні дзвінки здійснюються за допомогою програмних переривань. Такі інструкції, як sysenterоптимізовані шляхи викликів, оскільки контекстна комутація, що використовується обробниками переривань, не була такою швидкою, як всі бажали, але в принципі це все-таки програмне забезпечення, що генерується перериванням, при цьому обробляється за допомогою векторизації на обробник, встановлений ядром ОС. Частина процесу перемикання контексту, який виконується ІС, sysenter- це зміна бітів режиму в процесорі, щоб встановити кільце 0 - повний доступ до всіх привілейованих інструкцій, регістрів та пам'яті та вводу / виводу.
Бен Войгт

4

Ваша програма C ++ використовує бібліотеку Qt (також кодовану в C ++). Бібліотека Qt використовує функцію Windows CreateWindowEx (яка була закодована в C всередині kernel32.dll). Або під Linux він може використовувати Xlib (також закодований в C), але він також може надсилати необроблені байти, які в протоколі X означають " Будь ласка, створіть для мене вікно ".

Пов’язане з вашим питанням catch-22 - це історична примітка, що "перший компілятор C ++ був написаний на C ++", хоча насправді це був компілятор C з кількома поняттями C ++, достатньо, щоб він міг скласти першу версію, яка потім могла скласти себе .

Аналогічно, компілятор GCC використовує розширення GCC: спочатку компілюється у версію, потім використовується для самої перекомпіляції. (Інструкції зі створення GCC)


2

Як я бачу питання, це насправді питання компілятора.

Подивіться на це таким чином, ви пишете фрагмент коду в асамблеї (ви можете це зробити будь-якою мовою), який переводить вашу щойно написану мову, яку ви хочете викликати Z ++, в асамблею, а простота дозволяє називати її компілятором (це компілятор) .

Тепер ви даєте цьому компілятору деякі основні функції, щоб ви могли писати int, string, масиви тощо. Насправді ви даєте йому достатньо здібностей, щоб ви могли написати сам компілятор у Z ++. і тепер у вас є компілятор для Z ++, написаний на Z ++, досить акуратно правильно.

Що ще крутіше, це те, що тепер ви можете додати здібності до цього компілятора, використовуючи здібності, які він вже має, розширивши мову Z ++ новими можливостями за допомогою попередніх функцій

Наприклад, якщо ви пишете достатньо коду, щоб намалювати піксель у будь-якому кольорі, ви можете розгорнути його за допомогою Z ++, щоб намалювати все, що завгодно.


0

Апаратне забезпечення - це те, що дозволяє це зробити. Ви можете розглядати графічну пам'ять як великий масив (що складається з кожного пікселя на екрані). Для малювання на екрані ви можете записувати в цю пам'ять за допомогою C ++ або будь-якої мови, що дозволяє отримати прямий доступ до цієї пам'яті. Ця пам'ять просто може бути доступною для відеокарти або розміщеною на ній.

У сучасних системах для прямого доступу до графічної пам’яті потрібно буде написати драйвер через різні обмеження, тому ви використовуєте непрямі засоби. Бібліотеки, які створюють вікно (насправді просто зображення, як і будь-яке інше зображення), а потім записують це зображення у графічну пам’ять, яку потім відображає на екрані GPU. Нічого не потрібно додавати до мови, крім можливості запису до певних місць пам'яті, для чого потрібні покажчики.


Суть, яку я намагався зробити, - це те, що мові не потрібно «розширюватись» у тому сенсі, що нову версію мови потрібно переписувати, і що вона насправді не є круговою, оскільки робити щось цікаве програму повинен взаємодіяти з обладнанням.
Джон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.