カスタム関数 > カスタム関数用 C プログラムの記述
カスタム関数用 C プログラムの記述
PTC Mathcad のカスタム関数の記述を始めるために、多数のコードサンプルが含まれています。ファイル MULTIPLY.C (PTC Mathcad インストールディレクトリの Custom Functions/multiply サブフォルダ内) を参照します。MULTIPLY.C にはスカラーを配列に掛け合わせる 2 引数関数が含まれます。コンパイルして正しくリンクすると、PTC Mathcad を再起動したときに新しい関数 multiply(a, M) が使用できるようになります。
MULTIPLY.C のコードの詳細な説明については後述します。コード全体を表示するには、ファイルを Visual Studio または任意のテキストエディタで開きます。
ヘッダー
#include "mcadincl.h"
C プログラムには mcadincl.h ヘッダーファイル (PTC Mathcad インストールディレクトリの Custom Functions サブディレクトリ内) を含める必要があります。このファイルには次の操作を実行可能にするデータ構造が含まれます。
PTC Mathcad が読み取ることのできる関数を定義します。
PTC Mathcad と互換性を確保してスカラーや配列の割り当てや解放を行います。
グラフィカルユーザーインタフェースを使用して、PTC Mathcad に返すエラーメッセージを作成します。
エラーメッセージ
一般に、発生する可能性のあるさまざまなタイプのエラーのエラーコードをプログラムの次の部分で定義します。不適切なデータタイプについてのエラーは必ずトラップします。これは、PTC Mathcad 関数の誤った使用方法のうち最もよくあるものです。これらは一緒に定義して、エラーの合計数を計測しやすくします。この合計は 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 では、オーバーフロー、0 による除算、無効操作などの浮動小数点例外をトラップします。これらの例外が発生した場合、PTC Mathcad には関数の下に浮動小数点エラーメッセージが表示されます。これらのエラーのいずれかが発生すると、PTC Mathcad はすべての割り当て済みメモリも解放します。
アルゴリズム
次に、アルゴリズムを実行するコードについて説明します。既存のライブラリのコードを変換する場合、PTC Mathcad によって渡され、期待される COMPLEXARRAYCOMPLEXSCALAR、および MCSTRING タイプで再提示する必要があります。
アルゴリズムの 1 つ目の引数は戻り値に対するポインタであり、この場合は Product です。残りの引数は 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;
}
関数の PTC Mathcad への登録
FUNCTIONINFO 構造に、関数を PTC Mathcad に登録する際に必要な情報を記入します。この構造は PTC Mathcad で関数の名前を定義します。アルゴリズムの名前 MultiplyRealArrayByRealScalar ではありません。パラメータや説明、使用するアルゴリズムへのポインタも定義します。
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}
};
ライブラリのダイナミックリンク
DLL は Dynamic Link Library (ダイナミックリンクライブラリ) の略です。次のコードによりこのライブラリが Windows の DLL インタフェースを経由してその他の Windows 関数、特に PTC Mathcad で使用できるようになります。プログラミング環境を通じてエントリポイントへの参照を指定する必要もあります。DLL がロードされると、オペレーティングシステムで DLL のエントリポイントが呼び出されます。PTC Mathcad では、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;
エラーメッセージテーブルと関数の登録
関数がエラーを返さない場合、エラーメッセージテーブルは不要です。エラーメッセージテーブルは DLL ごとに 1 つだけ登録できますが、DLL には 2 つ以上の関数を登録できます。残りのプロセスや定義のクリーンアップも必要です。
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
追加情報
PTC Mathcad に受け渡されるすべての値は、その構造に実部と虚部の両方を持つ複素数です (mcadincl.h を参照)。実部と虚部を独立に扱おうとする場合、これらを分割する必要があります。
配列では最初に列に添字を設定し、次に行に添字を設定します。これは、PTC Mathcad 内の添字の順序 (最初に行、次に列) とは逆です。
すべての配列が 2 次元と見なされます。ベクトルを参照する場合、最初の配列の添字 (列) を 0 に設定します。
これは役に立ちましたか?