Ecriture de programmes C pour les fonctions personnalisées
Pour commencer à écrire des fonctions personnalisées pour PTC Mathcad, un certain nombre d'exemples de code sont inclus. Consultez le fichier MULTIPLY.C situé dans le sous-répertoire Custom Functions\multiply de votre répertoire d'installation PTC Mathcad. MULTIPLY.C contient une fonction d'argument qui multiplie un scalaire par un tableau. Lorsque vous compilez et liez correctement la nouvelle fonction multiply(a, M), elle devient disponible lorsque vous redémarrez PTC Mathcad.
Voici une description détaillée du code dans MULTIPLY.C. Pour afficher le code dans son intégralité, ouvrez le fichier dans Visual Studio ou tout éditeur de texte.
En-têtes
#include "mcadincl.h"
Votre programme C doit inclure le fichier d'en-tête mcadincl.h, situé dans le sous-répertoire Custom Functions du répertoire d'installation PTC Mathcad. Ce fichier contient les structures de données qui vous permettent d'effectuer les actions suivantes :
• Définissez les fonctions que PTC Mathcad peut lire.
• Allouez et libérez les scalaires et tableaux d'une manière compatible avec PTC Mathcad.
• Créez des messages d'erreur qui peuvent être renvoyés à PTC Mathcad à l'aide de l'interface utilisateur graphique.
Messages d'erreur
En général, la partie suivante du programme définit les codes d'erreur pour les types d'erreurs auxquels vous pouvez vous attendre. Assurez-vous de déceler les erreurs pour les types de données inappropriés, car ils font partie des mauvaises utilisations les plus courantes des fonctions PTC Mathcad. Ces erreurs sont définies ensemble, il est donc facile de les dénombrer. Ce total est requis par la fonction CreateUserErrorMessageTable.
// 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 décèle les exceptions de virgule flottante suivantes : dépassement, division par zéro et opération non valide. Dans le cas de ces exceptions, PTC Mathcad affiche un message d'erreur de virgule flottante sous la fonction. PTC Mathcad libère également toute la mémoire allouée lorsque l'une de ces erreurs se produit.
Algorithme
Vient ensuite le code qui exécute votre algorithme. Si vous convertissez le code à partir d'une bibliothèque existante, vous devez le refondre avec les types COMPLEXARRAY, COMPLEXSCALAR et MCSTRING transmis et attendus par PTC Mathcad.
Le premier argument de l'algorithme est un pointeur vers la valeur renvoyée, dans ce cas, Product. Les arguments restants sont des pointeurs vers les valeurs d'entrée provenant de 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; }
Enregistrement de la fonction avec PTC Mathcad
Remplissez une structure FUNCTIONINFO avec les informations nécessaires pour enregistrer la fonction avec PTC Mathcad. Cette structure définit le nom de la fonction dans PTC Mathcad et pas le nom de l'algorithme MultiplyRealArrayByRealScalar. Elle définit également les paramètres et une description, ainsi qu'un pointeur vers l'algorithme utilisé.
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} };
Liaison dynamique de la bibliothèque
DLL signifie Dynamic Link Library (bibliothèque de liens dynamiques). Le code suivant rend cette bibliothèque disponible aux autres fonctions Windows, en particulier PTC Mathcad, via l'interface DLL de Windows. Vous devez aussi spécifier une référence au point d'entrée à travers votre environnement de programmation. Le point d'entrée DLL est appelé par le système d'exploitation lorsque le fichier DLL est chargé. PTC Mathcad nécessite d'enregistrer vos fonctions courantes et votre table de messages d'erreur lors du chargement du fichier 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;
Enregistrement de la table de messages d'erreur et de la fonction
Si votre fonction ne renvoie jamais d'erreur, une table de messages d'erreur n'est pas requise. Vous ne pouvez enregistrer qu'une table de messages d'erreur par DLL, mais vous pouvez enregistrer plusieurs fonctions. Vous pouvez aussi nettoyer tous les processus ou définitions restants.
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
Informations supplémentaires
• Toutes les valeurs transmises vers et depuis PTC Mathcad sont des complexes, puisque leur structure comprend une partie réelle et une imaginaire (voir mcadincl.h) Vous devez séparer les parties réelle et imaginaire si vous avez l'intention de les manipuler indépendamment.
• Les tableaux sont indexés par colonne, puis ligne, contrairement à l'ordre des indices dans PTC Mathcad, qui est par ligne, puis colonne.
• Tous les tableaux sont considérés comme ayant deux dimensions. Si vous souhaitez référencer un vecteur, définissez le premier index de tableau (colonne) sur 0.