C-Programme für angepasste Funktionen schreiben
Um Ihnen den Einstieg in das Erstellen angepasster Funktionen für PTC Mathcad zu erleichtern, werden verschiedene Codebeispiele bereitgestellt. Betrachten Sie dazu die Datei MULTIPLY.C im Unterverzeichnis Custom Functions/multiply des PTC Mathcad Installationsverzeichnisses. MULTIPLY.C enthält eine Funktion mit zwei Argumenten, die einen Skalar mit einem Array multipliziert. Wenn Sie sie kompilieren und richtig verknüpfen, wird die neue Funktion multiply(a, M) beim Neustart von PTC Mathcad verfügbar.
Es folgt eine detaillierte Beschreibung des Codes in MULTIPLY.C. Um den Code vollständig zu sehen, öffnen Sie die Datei in Visual Studio oder einem Texteditor.
Kopfzeilen
#include "mcadincl.h"
Das C-Programm muss die Kopfzeilendatei mcadincl.h einschließen, die sich im Unterverzeichnis Custom Functionsdes PTC Mathcad Installationsverzeichnisses befindet. Diese Datei enthält die Datenstrukturen, mit denen Sie die folgenden Aktionen ausführen können:
• Definieren Sie Funktionen, die PTC Mathcad lesen kann.
• Gehen Sie beim Zuordnen und Freigeben von Skalaren sowie Arrays auf eine mit PTC Mathcad kompatible Weise vor.
• Erstellen Sie Fehlermeldungen, die über die grafische Benutzeroberfläche an PTC Mathcad zurückgegeben werden können.
Fehlermeldungen
Gewöhnlich werden im nächsten Teil des Programms Fehlercodes für die Arten möglicherweise auftretender Fehler festgelegt. Fangen Sie auf jeden Fall Fehler wegen unpassender Datentypen ab, denn Fehler dieser Art treten bei PTC Mathcad Funktionen am häufigsten auf. Da diese Fehlercodes zusammen festgelegt werden, kann die Gesamtzahl der Fehler ohne weiteres ermittelt werden. Diese Summe wird von der Funktion CreateUserErrorMessageTable benötigt.
#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 fängt die folgenden Gleitkommaausnahmen ab: Überlauf, Teilung durch null und ungültige Operation. Bei diesen Ausnahmen zeigt PTC Mathcad eine Gleitkommafehlermeldung unter der Funktion an. Wenn einer dieser Fehler auftritt, gibt PTC Mathcad außerdem auch den gesamten zugeordneten Arbeitsspeicher frei.
Algorithmus
Es folgt der Code, mit dem der Algorithmus ausgeführt wird. Wenn Sie Code aus einer vorhandenen Bibliothek konvertieren, müssen Sie ihn mit den Typen COMPLEXARRAY, COMPLEXSCALAR und MCSTRING umarbeiten, die von PTC Mathcad übergeben und erwartet werden.
Das erste Argument des Algorithmus ist ein Zeiger zum Rückgabewert, in diesem Fall Product. Die übrigen Argumente sind Zeiger auf die aus PTC Mathcad stammenden Eingabewerte.
// 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;
}
Funktionen in PTC Mathcad registrieren
Füllen Sie eine FUNCTIONINFO-Struktur mit den Informationen, die erforderlich sind, um die Funktion in PTC Mathcad zu registrieren. Diese Struktur definiert den Namen der Funktion innerhalb von PTC Mathcad, nicht jedoch den Namen des Algorithmus MultiplyRealArrayByRealScalar. Sie definiert auch die Parameter und eine Beschreibung sowie einen Zeiger zum verwendeten Algorithmus.
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}
};
Bibliotheken dynamisch verknüpfen
DLL bedeutet Dynamic Link Library. Mit dem folgende Code wird diese Bibliothek über die DLL-Schnittstelle von Windows anderen Windows-Funktionen zur Verfügung gestellt, insbesondere PTC Mathcad. Über die Programmierumgebung müssen Sie auch eine Referenz auf den Eintrittspunkt angeben. Der DLL-Eintrittspunkt wird beim Laden der DLL vom Betriebssystem aufgerufen. PTC Mathcad verlangt die Registrierung der angepassten Funktionen und der Fehlermeldungstabelle beim Laden der 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;
Fehlermeldungstabelle und Funktion registrieren
Wenn Ihre Funktion nie einen Fehler zurückgibt, ist keine Fehlermeldungstabelle erforderlich. Pro DLL können Sie nur eine Fehlermeldungstabelle registrieren, aber Sie können mehrere Funktionen pro DLL registrieren. Zudem müssen Sie verbleibende Prozesse oder Definitionen bereinigen.
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
Zusätzliche Informationen
• Alle Werte, die an und von PTC Mathcad übergeben werden, sind komplex, und ihre Struktur enthält sowohl einen Realteil als auch einen Imaginärteil (siehe mcadincl.h). Sie müssen den Realteil und den Imaginärteil trennen, wenn Sie sie unabhängig voneinander bearbeiten möchten.
• Arrays werden nach der Spalte und dann nach der Zeile indiziert; bei Indizes in PTC Mathcad ist die Reihenfolge hingegen umgekehrt (erst nach Zeile, dann nach Spalte).
• Bei allen Arrays wird angenommen, dass sie zwei Dimensionen haben. Wenn Sie einen Vektor referenzieren möchten, legen Sie den ersten Arrayindex (Spalte) auf 0 fest.