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

         

Связь между Приложениями


Функция ObjectARX acedInvoke () в одном приложении используется, чтобы вызвать внешние функции, определенные и осуществленные другими приложениями ObjectARX.

Внешняя функция, вызванная acedInvoke() должна быть определена в настоящее время загруженным ObjectARX-приложением.

AcedInvoke() функция вызывает внешнюю функцию именем, что его приложение определило в acedDefun() запрос, который является именем функции, что AutoLISP вызывает, чтобы вызвать функцию. Если внешняя функция была определена как команда AutoLISP, с “ C: ” как префикс к его имени, эти символы должны быть включены в строку, как которая acedInvoke () определяет (когда команда вызвана с выражением AutoLISP).

ПРЕДУПРЕЖДЕНИЕ! Поскольку приложения, загруженные в то же самое время не могут иметь двойные имена функции, Вы должны брать это во внимание при проектировании приложения, которое использует больше чем единственный программный файл; избегите проблемы со схемой обозначения или соглашением, которое гарантирует, что имя каждой внешней функции будет уникально. Лучшее решение состоит в том, чтобы использовать ваш Зарегистрированный Символ Разработчика (RDS) как префикс.

Имя внешней функции, и любых значений параметра, которых это требует, пропускают к acedInvoke() в форме списка связей буферов результатов. Это также возвращает его результат в списке буфера результата; второй параметр к acedInvoke () - адрес указателя буфера результата.

Следующая типовая функция вызывает acedInvoke () чтобы вызвать факт функции факториала () в типовой программе fact.cpp:

static void test()

{

int stat, x = 10;

struct resbuf *result = NULL, *list;

// Get the factorial of x from file fact.cpp.

list = acutBuildList(RTSTR, "fact", RTSHORT, x, RTNONE);

if (list != NULL) {

stat = acedInvoke(list, &result);

acutRelRb(list);

}



if (result != NULL) {

acutPrintf("\nSuccess: factorial of %d is %d\n", x, result->resval.rint);

acutRelRb(result);

}

else

acutPrintf("Test failed\n");


}

Если функция, как предполагается,  будет вызвана с acedInvoke(), приложение, которое определяет это, должен регистрировать функцию,  вызывая acedRegFunc(). (В некоторых случаях acedRegFunc() запрос требован, как описано позже в этой секции.)

Когда acedRegFunc() вызван, чтобы регистрировать функцию, ObjectARX вызывает функцию непосредственно, без того, чтобы пройти цикл отправки приложения. Чтобы определять функцию, вызовите acedRegFunc ().

Внешний функциональный обработчик, зарегистрированный acedRegFunc() не должен иметь никакие параметры и должен возвратить целое число (который является одним из прикладного результата, закодирует — или RSRSLT или RSERR).

Следующая выборка показывает, как funcload () функция в fact.cpp может изменяться, чтобы регистрировать ее функции также как определять их:

typedef int (*ADSFUNC) (void);

// Сначала, определите структуру таблицы: строка, дающая имя AutoCAD функции,

//  и указателя на функцию, возвращающую тип int.

struct func_entry {char *func_name; ADSFUNC func;};

// Объявить функции, которые обрабатывают, вызывает.

int fact (void); // Remove the arguments

int squareroot (void);

// Здесь мы определяем массив имен функции и обработчиков.

//

static struct func_entry func_table[] =

{              {"fact", fact},

{"sqr", squareroot},

};

...

static int funcload()

{

int i;

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

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

return RTERROR;

if (!acedRegFunc(func_table[i].func, i))

return RTERROR;

}

return RTNORM;

}

Как показывают выборки кода, первый параметр к acedRegFunc () - указатель функции (названный по имени функциональный обработчик, определенный в исходном тексте), а не внешнее имя функции, определенное acedDefun () и вызванный AutoLISP или acedInvoke (). И acedDefun () и acedRegFunc () передают тот же самый целочисленный функциональный код .

Если зарегистрированная функция должна отыскать параметры, это должно делать так,  делая ее собственный запрос к acedGetArgs ().



AcedGetArgs () запрос перемещен, чтобы быть в пределах функционального fact(). Указатель буфера результата rb сделан переменной скорее чем параметр. (Это не соответствует запросу к fact () в dofun () функция. Если все внешние функции зарегистрированы, поскольку этот пример принимает, dofun () функция может быть удалена полностью; см. примечание, которое следует за этим примером.) новый код показывается в типе жирного начертания:

static int fact()

{

int x;

struct resbuf *rb;

rb = acedGetArgs();

if (rb == NULL)

return RTERROR;

if (rb->restype == RTSHORT) {

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

} else {

acdbFail("Argument should be an integer.");

return RTERROR;

}

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

acdbFail("Argument should be positive.");

return RTERROR;

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

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

return RTERROR;

}

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

// return the value to AutoLISP.

return RTNORM;

}

Сопоставимое изменение было бы должно быть сделано к squareroot().

ОБРАТИТЕ ВНИМАНИЕ, вызывает ли приложение acedRegFunc() чтобы регистрировать обработчик для каждой внешней функции, это определяет, это может предполагать, что эти функции будут вызваны acedInvoke(), и это может опустить kInvkSubrMsg случай acrxEntryPoint () функция. Если Вы проектируете приложение, которое требует больше чем единственный файл кода ObjectARX, эта методика предпочтительна, потому что это размещает бремя обработки функции, вызывает ObjectARX библиотеку скорее чем на acrxEntryPoint() функцию.

Если функциональный запрос начинает последовательность запроса, которая заставляет функцию в том же самом приложении быть вызванной с acedInvoke (), последняя функция должна быть зарегистрирована acedRegFunc(). Если вызванная функция не зарегистрирована, acedInvoke () сообщает о ошибке. Следующий рисунок иллюстрирует эту ситуацию:





В иллюстрации выше,

§         A_tan () вызывает B_sin ()

§         A_tan () вызывает C_cos ()

§         B_sin () вызывает A_pi ()

§         C_cos () вызывает A_pi ()

Где приложение A определяет A_tan () и A_pi (), приложение B определяет B_sin (), и приложение C определяет C_cos (). A_pi () функция должен быть зарегистрирован acedRegFunc().

Чтобы предотвращать acedInvoke() от сообщающих ошибок регистрации, регистрируйте любую внешнюю функцию, которая, как предполагается,  будет вызвана с acedInvoke().

AcedRegFunc() функция может быть вызван также, чтобы нерегистрировать внешнюю функцию. То же самое приложение должно или регистрировать или нерегистрировать функцию; ObjectARX запрещает приложение от непосредственно управления другим приложением.


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