為自訂函數編寫 C 程式
為協助您開始編寫 PTC Mathcad 的自訂函數,以下包含一些程式碼樣本。請參考位於您的 PTC Mathcad 安裝目錄之 Custom Functions/multiply 子目錄中的檔案 MULTIPLY.C。MULTIPLY.C 包含將純量乘以陣列的雙引數函數。當您加以編譯並正確地連結函數之後,新函數 multiply(a, M) 會在您重新啟動 PTC Mathcad 之後,可供使用。
以下是 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 會設陷下列浮點例外:溢位、除以零及無效的操作。若發生這些例外,PTC Mathcad 會在函數下方顯示浮點錯誤訊息。PTC Mathcad 也會在發生下列其中一種錯誤時,釋放所有分配的記憶體。
演算法
下一部份是執行演算法的程式碼。若要從現有的程式庫轉換程式碼,必須使用 PTC Mathcad 傳遞及預期的 COMPLEXARRAY、COMPLEXSCALAR 及 MCSTRING 類型重新轉換。
演算法的第一個引數指向傳回值,在此案例中為 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 註冊函數
使用透過 PTC Mathcad 註冊函數所需的資訊填寫 FUNCTIONINFO 結構。此結構定義 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 代表動態連結程式庫。下列程式碼可讓其他視窗型函數 (特別是 PTC Mathcad) 透過 Windows 的 DLL 介面使用此程式庫。您也必須指定程式編寫環境之進入點的參照。作業系統會在載入 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 只能註冊一個錯誤訊息資料表,但每個 DLL 可註冊多個函數。您也必須清除其餘所有流程或定義。
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 內的索引編製順序相反 (先編製列索引,再編製欄索引)。
• 所有陣列都假設具有兩個維度。若想參照向量,請將第一個陣列索引 (欄) 設為 0。