AutoLISP este mort, traiasca C++!

De Mircea PANTEA

Obiectul este subiectul

De la aparitia pe piata a pachetului AutoCAD R12 pâna la lansarea lui R13 s-a scurs o perioada de timp neobisnuit de lunga. Unele voci se întrebau: ce se întâmpla cu Autodesk? Realitatea este ca în acest interval de timp s-a trecut de la arhitectura C la arhitectura C++ si de la platforma DOS la Windows. Ce s-a întâmplat de fapt? Utilizatorii nu au sesizat diferente notabile între cele doua versiuni. Ba unii si-au amintit cu regret de viteza si stabilitatea AutoCAD-ului R12. În realitate produsul a fost regândit si reproiectat, asa cum îi sta bine unei aplicatii serioase. Totul, cu un efort mare, iar gurile rele spun ca Autodesk a iesit abia de câteva saptamâni din asanumitul "management de criza". Nedumerirea persista, în continuare: si ce e cu aceasta? Raspunsul poate fi dat acum, dar primele rezultate vor fi vizibile abia dupa ce vor fi lansate pe piata noile aplicatii sub AutoCAD, bazate pe tehnologiile moderne. Care sînt aceste tehnologii si ce posibilitati se deschid dezvoltatorilor de aplicatii sub mediul AutoCAD? Este suficient sa enumeram câteva acronime pentru a va incita: MFC, ARX, ODBC, OLE, COM, totul în, lânga, peste sau sub AutoCAD si totul "orientat obiect".

Când am avut la dispozitie prima versiune alfa a noului AutoCAD R13, am remarcat câteva lucruri ciudate, pentru care explicatiile au fost furnizate abia peste câteva luni. Primul element frapant a fost noul mediu de dezvoltare, numit ARX (nu ma întrebati ce înseamna; o fi ceva cu "AutoCAD" si "eXtension"), care permite dezvoltarea de aplicatii în C++. Faptul în sine este notabil dar nedumeririle au persistat pâna pe la sfârsitul anului 1995, când am primit primul AutoCAD R13 c4, care avea si un SDK (asta stiu ce înseamna: Software Development Kit). Din acest moment s-a deschis un nou univers si am înteles toate misterele pe care le-am vazut în seria de versiuni intermediare sau pe care Autodesk le-a lasat sa scape din când în când.

Sa începem cu începutul

O aplicatie ARX este un DLL care se leaga de executabilul AutoCAD. În sistemul de operare Windows NT, fiecare aplicatie primeste o zona de memorie din care nu poate sa iasa sub nici o forma. Orice tentativa de scriere sau doar citire din afara acestei zone este sanctionata cu o eroare. Un program DLL, desi a fost generat în mod independent, împarte aceeasi zona de memorie cu programul principal. Cu alte cuvinte, codul binar al fisierului DLL se comporta ca si cum ar face parte integranta din programul care l-a apelat. Desi comparatia este putin fortata, a scrie o aplicatie ARX este ca si cum am avea fisierele sursa ale AutoCAD-ului si am scrie aplicatia noastra în continuare, dupa care, la compilare s-ar obtine un tot unitar. Lucrurile nu stau chiar asa, din simplul motiv ca aplicatia noastra nu "vede" din AutoCAD decât ceea ce producatorul considera necesar. Oricum, comunicarea dintre AutoCAD si aplicatia noastra se face cu maximum de eficienta. De asemenea, erorile din aplicatia noastra se comporta ca si cum ar fi din AutoCAD iar efectul este spectaculos: o eroare ARX descarca în mod instantaneu si AutoCAD-ul. Destul de neplacut, deoarece acesta nici macar nu apuca sa ne comunice un mesaj sau sa ne dea sansa sa salvam desenul. Din acest motiv, aplicatiile ARX trebuie sa fie realizate impecabil.

În acest articol ne propunem sa analizam diversele moduri în care poate fi scris un program simplu sub AutoCAD. Vom face un program care sa traseze o linie între doua puncte date, folosind AutoLISP, ADS si ARX. Cine vrea sa ma urmareasca, va trebui sa aiba un calculator ceva mai puternic, Windows NT 3.51, AutoCAD R13 c4 si Microsoft Visual C++ 2.2( sau 4.0), for Windows, bineînteles.

AutoLISP

Începem cu ce este mai usor si anume cu AutoLISP-ul. Pentru asta nu avem nevoie decât de AutoCAD (vezi sursa).

Programul este banal si inutil, dar ne va folosi ca referinta în compararea tehnicilor de programare. Daca nu cunoasteti AutoLISP, C sau C++, este momentul sa va opriti, deoarece nu ne vom referi la elementele de baza, ci le voi considera cunoscute de catre cititor.

ADS

Pentru a scrie acelasi program în ADS va trebui sa facem câteva pregatiri:

lansam Visual C++ 2.0 si începem un proiect nou: File -> new -> project -> OK. Dupa aceea îl botezam "line1" si la "Project type" alegem "Application" si apoi Create.

Dupa toate astea, obtinem mesajul "line1.exe - 0 error(s), 0 warning(s)" si îl încarcam în AutoCAD. Astfel am obtinut aceeasi comanda, dar de data aceasta avem o aplicatie ADS. Daca stam sa analizam sursa LISP si sursa C, observam destul de multe similitudini. În afara declaratiilor, sursele sînt aproape identice. Diferenta functionala este doar viteza de executie, care este mult mai mare pentru aplicatia ADS, dar în acest caz nu prea avem cum sa o sesizam.

ARX

Acum sa ne luam inima în dinti si sa facem acelasi lucru în ARX. Pentru aceasta vom schimba setarile compilatorului, dupa cum urmeaza:

Dupa compilare si linkeditare vom obtine fisierul "line1a.dll". Dupa încarcare (rxload "line1a.dll"), tastam comanda "line1a" si obtinem aceeasi linie, ca în exemplele anterioare.

Acest exemplu nu este, nici pe departe, relevant în privinta posibilitatilor pe care tehnica ARX ni le pune la dispozitie, dar trebuie sa începem cu ceva. O analiza a surselor ne arata ca exista diferente majore între tehnica ADS si ARX, înca de la definirea comenzilor. Astfel, daca în ADS cream o functie care reactioneaza la nivelul interpretorului LISP, în ARX avem acces direct la tabela de definire a comenzilor AutoCAD, unde putem face tot ceea ce dorim. În exemplul nostru, am creat grupul de comenzi "MY_COMMANDS" în care am definit comanda "line1a". În mod asemanator, am putea sa redefinim comenzile standard sau sa adaugam o noua comanda în grupul ACAD. De asemenea, putem sa definim o comanda care sa poarte acelasi nume cu una standard si sa o plasam înaintea comenzii originare, astfel încât comanda noastra sa fie executata în mod preferential. Apoi, în timpul executiei programului, putem muta comanda noastra la coada listei de comenzi, în asa fel încât, functie de o decizie, sa fie executata comanda standard.

Pentru a desena o linie vom apela constructorul obiectului AcDbLine si vom plasa obiectul nou creat în tabela de blocuri din desenul curent. Din acest moment obiectul nostru este preluat de catre mecanismele de persistenta ale AutoCAD-ului si gestionat în continuare. Acesta este si motivul pentru care nu avem voie sa eliberam noul obiect cu "delete". Daca am încerca, asa cum spune regula, sa eliberam obiectul la iesirea din functie cu ceva de genul:

delete [] pLine;

am obtine o eroare fatala de toata frumusetea. Puteti sa încercati.

Dupa cum probabil intuiti, putem sa desenam si în alte fisiere decât cel deschis de catre AutoCAD, deoarece ARX-ul poate sa deschida si sa administreze oricâte fisiere, pe care le trateaza ca pe niste baze de date orientate obiect. Prin asemenea mecanisme putem sa lucram cu mai multe fisiere DWG desi numai unul este vizualizat de catre AutoCAD, la un moment dat. Ati observat ca am folosit notiunea de tabela de blocuri. Nu trebuie sa cadem în capcana de a crede ca am creat un bloc, deoarece asa se numeste tabela unde sînt depuse toate entitatile vizibile dintr-un desen. În principiu, cu ajutorul tehnicilor ARX se poate defini în AutoCAD o entitate noua, care sa aiba proprietati geometrice si non-geometrice definite de catre noi. Sa va asteptati la o entitate care poate sa aiba puncte "grips" si puncte "osnap" unde hotarâm noi, care sa se desfaca în ce hotarâm noi, la comanda "explode", sa afiseze ce dorim noi în cazul în care lansam comanda "list", care sa anunte aplicatia noastra ca se executa o comanda de editare asupra sa (copy/move/scale etc.). Cu alte cuvinte, o entitate care este altceva decât cele cu care am fost siliti sa lucram pâna acum. Atentie dezvoltatori: stati pe aproape.

Sursa AutoLISP

Fisierul AUTOLISP.LSP

Surse ADS

Fisierul FUNCDEF.H
Fisierul FUNCDEF.CPP
Fisierul LINE1.CPP
Fisierul MAIN.H
Fisierul MAIN.CPP

Surse ARX

Fisierul LINE1A.CPP
Fisierul LINE1A.DEF
Fisierul MAIN1.CPP

Sursa completa a programului o gasiti în BBS (vezi pag. 8). Vom discuta acum, cât spatiul ne-o va permite, câteva detalii despre program.

Subrutina de depistare a separatorului search$ permite folosirea în fisierul de date a oricarui separator, nu numai virgula cum am dat exemplu la începutul articolului. Functia are ca parametrii de intrare linia citita din fisierul de date lin (care se atribuie lui st:1) si tipul separatorului st:2. Subrutina returneaza o lista cu n+1 elemente, de tip sir (string), unde n este numarul de separatori depistati. Daca aveti fisiere cu alt tip de separator, schimbati în linia de apelare a subrutinei (search$ lin ",") virgula cu separatorul propriu.

Subrutina de inversare a coordonatelor r=lst. Aceasta ofera posibilitatea lucrului cu doua sisteme de coordonate: Stereo33, sau Stereo70. Indiferent de sistemul de coordonate folosit la culegerea datelor din teren, în fisierul de date se trec valorile reale pentru X si Y.

Subrutina de înscriere a licentelor reciteste liniile din fisierul de date, (setq lin (read-line fr)), le sare pe acelea care încep cu blanc (titluri), verifica ordinea coordonatelor (variabila a:sw), dupa care deseneza un punct (command "point" p:ct), rosu (setq "color" 1) în fiecare vertex al poliliniei unde urmeaza sa se puna o licenta de tip LEADER (implicit), sau TEXT când se apasa butonul din dreapta al mouse-ului, actiune depistata de (if (= (type p:ctmp) nil)).

Nae Bitoaica este inginer, în cadrul Universitatii Politehnice Bucuresti, Facultatea IMST, specialist în programare AutoLISP si ADS si poate fi gasit la tel: 01-410-45-85 int. 151

(C) Copyright Computer Press Agora