Funzioni personalizzate > Scrittura di programmi C per funzioni personalizzate
  
Scrittura di programmi C per funzioni personalizzate
Sono disponibili alcuni esempi di codice per acquisire familiarità con la scrittura di funzioni personalizzate per PTC Mathcad. Fare riferimento al file MULTIPLY.C disponibile nella sottodirectory Custom Functions\multiply della directory di installazione di PTC Mathcad. MULTIPLY.C contiene una funzione con due argomenti che moltiplica uno scalare per un array. Quando viene compilata e collegata correttamente, la nuova funzione multiply(a, M) diventa disponibile al riavvio di PTC Mathcad.
Segue una descrizione dettagliata del codice di MULTIPLY.C. Per visualizzare interamente il codice, aprire il file in Visual Studio o in qualsiasi editor di testo.
Intestazioni
#include "mcadincl.h"
Il programma C deve includere il file di intestazione mcadincl.h, disponibile nella sottodirectory Custom Functions della directory di installazione di PTC Mathcad. Il file contiene le strutture dei dati che consentono di eseguire le azioni indicate di seguito.
Definire funzioni che PTC Mathcad sia in grado di leggere.
Allocare e liberare scalari e array in un modo compatibile con PTC Mathcad.
Creare i messaggi di errore che possono essere restituiti in PTC Mathcad utilizzando l'interfaccia grafica utente.
Messaggi di errore
In genere, la parte successiva del programma definisce codici di errore per i possibili tipi di errori che si prevede di riscontrare. Assicurarsi di intercettare gli errori per i tipi di dati non appropriati, in quanto rappresentano i casi di utilizzo non corretto più comuni delle funzioni di PTC Mathcad. Poiché vengono definiti insieme, è facile calcolare il numero totale di errori. Questo totale è necessario per la funzione CreateUserErrorMessageTable.
#define INTERRUPTED 1
#define INSUFFICIENT_MEMORY 2
#define MUST_BE_REAL 3
#define NUMBER_OF_ERRORS 3

// table of error messages
// if your function never returns an error -- you do not need to create this table
char * myErrorMessageTable[NUMBER_OF_ERRORS] =
{
"interrupted",.
"insufficient memory",
"must be real"
};
PTC Mathcad intercetta le eccezioni a virgola mobile seguenti: overflow, divisione per zero e operazione non valida. Se si verificano queste eccezioni, in PTC Mathcad viene visualizzato un messaggio di errore relativo alla virgola mobile al di sotto della funzione. Quando si verifica uno di questi errori, PTC Mathcad libera inoltre tutta la memoria allocata.
Algoritmo
Segue quindi il codice per l'esecuzione dell'algoritmo. Se si converte codice da una libreria esistente, è necessario trasformarlo con i tipi COMPLEXARRAY, COMPLEXSCALAR e MCSTRING passati e previsti da PTC Mathcad.
Il primo argomento per l'algoritmo è un puntatore al valore restituito, in questo caso Product. Gli argomenti rimanenti sono puntatori ai valori di input provenienti da PTC Mathcad.
// this code executes the multiplication
LRESULT MultiplyRealArrayByRealScalar( COMPLEXARRAY * const Product,
LPCCOMPLEXSCALAR Scalar, LPCCOMPLEXARRAY Array )
{
unsigned int row, col;
// check that the scalar argument is real
if ( Scalar->imag != 0.0)
// if it is not, display "must be real" error message
// under the scalar argument ( the 1st argument )
return MAKELRESULT( MUST_BE_REAL, 1)

// check that the array argument is real
if ( Array->hImag != NULL )
// if it is not, display "must be real" error message
// under the array argument ( the 2nd argument )
return MAKELRESULT( MUST_BE_REAL, 2);

// allocate memory for the product
if( !MathcadArrayAllocate( Product, Array-rows,Array-cols,
TRUE, // allocate memory for the real part
FALSE )) // do not allocate memory for the imaginary part

// if allocation is not successful, return with the appropriate error code
return INSUFFICIENT_MEMORY;

// if all is well so far -- go ahead and perform the multiplication
for ( col = 0; col < Product-> cols; col++ )
{
// check that a user has not tried to interrupt the calculation
if (isUserInterrupted())
{
// if user has interrupted -- free the allocated memory
MathcadArrayFree( Product );
// and return with an appropriate error code
return INTERRUPTED;
}
for ( row = 0; row < Product-> rows; row++ )
Product->hReal[col][row] =
Scalar-> real*Array-> hReal[col][row];
}

// normal return
return 0;
}
Registrare la funzione in PTC Mathcad
Completare una struttura FUNCTIONINFO con le informazioni necessarie per la registrazione della funzione in PTC Mathcad. Questa struttura definisce il nome della funzione in PTC Mathcad e non il nome dell'algoritmo MultiplyRealArrayByRealScalar. La struttura definisce inoltre i parametri e una descrizione, nonché un puntatore all'algoritmo utilizzato.
FUNCTIONINFO multiply =
{
// name by which Mathcad will recognize the function
"multiply",

// description of "multiply" parameters to be used
"a,M",

// description of the function
"returns the product of real scalar a and real array M",

// pointer to the executable code
// i.e. code that should be executed when a user types "multiply(a,M)="
(LPCFUNCTION)MultiplyRealArrayByRealScalar;

// multiply(a, M) returns a complex array
COMPLEX_ARRAY,

// multiply takes on two arguments
2,

// the first is a complex scalar, the second a complex array
{ COMPLEX_SCALAR, COMPLEX_ARRAY}
};
Collegare dinamicamente la libreria
DLL è l'acronimo di Dynamic Link Library, libreria a collegamento dinamico. Il codice indicato di seguito rende la libreria disponibile per altre funzioni di Windows, in particolare di PTC Mathcad, tramite l'interfaccia DLL di Windows. È inoltre necessario specificare un riferimento al punto di entrata tramite l'ambiente di programmazione. Il punto di entrata della DLL viene chiamato dal sistema operativo quando viene caricata la DLL. In PTC Mathcad è necessario registrare le funzioni predefinite e la tabella dei messaggi di errore durante il caricamento della DLL.
// DLL entry point code
// the _CRT_INIT function is needed if you are using Microsoft's 32-bit compiler

BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved);
BOOL WINAPI DllEntryPoint (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{    
case DLL_PROCESS_ATTACH:
// DLL is attaching to the address space of the current process
if (!_CRT_INIT(hDLL, dwReason, lpReserved))
return FALSE;
Registrare la tabella dei messaggi di errore e la funzione
Se la funzione non restituisce mai un errore, non è necessaria una tabella dei messaggi di errore. È possibile registrare solo una tabella dei messaggi di errore per DLL, ma per ogni DLL è possibile registrare più di una funzione. È inoltre necessario eliminare tutti i processi o le definizioni rimanenti.
if ( CreateUserErrorMessageTable( hDLL, NUMBER_OF_ERRORS, myErrorMessageTable ) )
// and if the errors register properly, register the user function
CreateUserFunction( hDLL, &multiply );
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
if (!_CRT_INIT(hDLL, dwReason, lpReserved))
return FALSE;
break;
}
return TRUE;
}
#undef INTERRUPTED
#undef INSUFFICIENT_MEMORY
#undef MUST_BE_REAL
#undef NUMBER_OF_ERRORS
Ulteriori informazioni
Tutti i valori passati verso e da PTC Mathcad sono complessi, poiché includono una parte reale e una immaginaria nella propria struttura (vedere mcadincl.h). Se si intende modificarle in modo indipendente l'una dall'altra, è necessario separare la parte reale da quella immaginaria.
Gli array vengono indicizzati per colonna e quindi per riga, al contrario dell'ordine degli indici all'interno di PTC Mathcad, che è prima per riga e quindi per colonna.
Si presuppone che tutti gli array abbiano due dimensioni. Se si desidera fare riferimento a un vettore, impostare il primo indice dell'array (colonna) su 0.