사용자 정의 함수 > 사용자 정의 함수의 C 프로그램 작성
  
사용자 정의 함수의 C 프로그램 작성
PTC Mathcad의 사용자 정의 함수를 작성할 수 있도록 많은 코드 샘플이 포함되어 있습니다. PTC Mathcad 설치 디렉토리의 Custom Functions\multiply 하위 디렉토리에 위치한 MULTIPLY.C 파일을 참조하십시오. MULTIPLY.C에는 인수가 두 개이며 스칼라 값과 배열을 곱하는 함수가 들어 있습니다. 이 함수를 컴파일하고 올바르게 링크한 후 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에서 전달하고 예상하는 COMPLEXARRAY, COMPLEXSCALARMCSTRING 형식으로 코드를 다시 캐스팅해야 합니다.
알고리즘의 첫 번째 인수는 반환 값(이 경우 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에 등록하는 데 필요한 정보를 입력합니다. 이 구조는 알고리즘 MultiplyRealArrayByRealScalar의 이름이 아니라 PTC Mathcad의 함수 이름을 정의합니다. 또한 매개변수, 설명 및 사용된 알고리즘에 대한 포인터를 정의합니다.
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당 하나만 등록할 수 있지만 함수는 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 내에서는 이와 반대로 지수가 행별로 지정된 다음 열별로 지정됩니다.
모든 배열은 2차원으로 간주됩니다. 벡터를 참조하려면 첫 번째 배열 지수(열)를 0으로 설정합니다.