ObjectARX, AutoCAD. Среда программирования библиотеки C++

       

Типовое ObjectARX-приложение


Сравните типовые приложения программ факториала, распределенных с AutoCAD. Программа fact.ccp - для среды программы ObjectARX, в то время как fact.c - для среды программы ADS. Следующая версия fact.cpp объявляет и осуществляет acrxEntryPoint (); иначе, fact.cpp почти идентичен fact.c. Функция acrxEntryPoint () заменяет главное в fact.c:

#include <stdio.h>

#include "adslib.h"

#include "rxdefs.h"

// Utility definition to get an array’s element count (at compile

// time). For example:

//

// int arr[] = {1,2,3,4,5};

// ...

// printf("%d", ELEMENTS(arr));

//

// would print a five. ELEMENTS("abc") can also be used to tell

// how many bytes are in a string constant INCLUDING THE TRAILING

// NULL.

#define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))

// All the functions that we’ll define will be listed in a single

// table, together with the internal function that we call to handle

// each. The functions all take a single argument (the resbuf that

// has the arguments) and return an integer (RTNORM or RTERROR for

// good or bad status).

// First, define the structure of the table: a string giving the

// AutoCAD name of the function, and a pointer to a function

// returning type int.

struct func_entry {

char *func_name;

int (*func) _((struct resbuf *));

};

// Here we declare the functions that handle the calls; at the moment

// there are two of them.

int fact _((struct resbuf *rb));

int squareroot _((struct resbuf *rb));

// Here we define the array of function names and handlers.

static struct func_entry func_table[] = {

{/*MSG0*/"fact", fact},

{/*MSG0*/"sqr", squareroot},

};

// To add more functions to this table, just put them in the list,

// after declaring the function names. Note that in standard C it’s

// all right to have a superfluous comma after the last item.

// The code from here to the end of dofun() is UNCHANGED when you


// add or delete functions.

// Declarations of other local functions:

void main _((int, char **));

int dofun _((void));

int funcload _((void));

ads_real rfact _((int x));

ads_real rsqr _((ads_real x));

// ACRXENTRYPOINT -- This function replaces main() for an ObjectARX

// program.

extern "C" AcRx::AppRetCode

acrxEntryPoint(AcRx::AppMsgCode msg, void* ptr)

{

switch(msg) {

case AcRx::kInitAppMsg:

acrxUnlockApplication(ptr);

break;

case AcRx::kInvkSubrMsg:

dofun();

break;

case AcRx::kLoadADSMsg:

funcload();

}

return AcRx::kRetOK;

}

// FUNCLOAD -- Define this application’s external functions.

// Return RTERROR on error, else RTNORM.

static int funcload()

{

int i;

for (i = 0; i < ELEMENTS(func_table); i++) {

if (!acedDefun(func_table[i].func_name, (short)i))

return RTERROR;

}

return RTNORM;

}

// DOFUN -- Execute external function (called upon an RQSUBR

// request). Return value from the function executed, RTNORM

// or RTERROR.

static int dofun()

{

struct resbuf *rb;

int val;

// Get the function code and check that it’s within range.

// (It can’t fail to be, but paranoia doesn’t hurt.)

if ((val = acedGetFunCode()) < 0 || val >= ELEMENTS(func_table))

{

acdbFail(/*MSG2*/"Received nonexistent function code.");

return RTERROR;

}

// Fetch the arguments, if any.

rb = acedGetArgs();

// Call the handler and return its success-failure status.

val = (*func_table[val].func)(rb);

acutRelRb(rb);

return val;

}

// The code from the beginning of main() to here is UNCHANGED when

// you add or delete functions.

// FACT -- First set up the argument, then call the factorial

// function.

static int

fact(struct resbuf *rb)

{

int x;

if (rb == NULL)

return RTERROR;

if (rb->restype == RTSHORT) {

x = rb->resval.rint; // Save in local variable

} else {

acdbFail(/*MSG3*/"Argument should be an integer.");

return RTERROR;

}

if (x < 0) { // Check argument range



acdbFail(/*MSG4*/"Argument should be positive.");

return RTERROR;

} else if (x > 170) { // Avoid floating-point overflow

acdbFail(/*MSG5*/" Argument should be 170 or less.");

return RTERROR;

}

acedRetReal(rfact(x)); // Call the function itself, and

// return the value to AutoLISP

return RTNORM;

}

// This is the implementation of the actual external factorial

// function.

static ads_real rfact(int n)

{

ads_real ans = 1.0;

while (n)

ans *= n--;

return ans;

}

// SQUAREROOT -- First set up the argument, then call the root

// function.

static int

squareroot(struct resbuf *rb)

{

ads_real x;

if (rb == NULL)

return RTERROR; // A proper error msg would

// be better.

if (rb->restype == RTSHORT) { // Save in local variable.

x = (ads_real) rb->resval.rint;

} else if (rb->restype == RTREAL) {

x = rb->resval.rreal; // Can accept either real

// or integer.

} else {

acdbFail(

/*MSG6*/

"Argument should be a real or integer value.");

return RTERROR;

}

if (x < 0) { // Check argument range.

acdbFail(/*MSG7*/"Argument should be positive.");

return RTERROR;

}

acedRetReal(rsqr(x)); // Call the function itself, and

// return the value to AutoLISP.

return RTNORM;

}

// This is the implementation of the actual external function

static ads_real rsqr(ads_real x) // Square root by Newton’s  method.

{

int n = 50;

ads_real y, c, cl;

if (x == 0.0) {

return 0.0;

}

y = (x * 2 + .1) / (x + 1.0);

c = (y - x / y) / 2;

cl= 0.0;

while ((c != cl) && (n-- > 0)) {

y -= c;

cl = c;

c = (y - x / y) / 2;

}

return y;

}


Содержание раздела