Community Tip - Want the oppurtunity to discuss enhancements to PTC products? Join a working group! X
Hi,
Function to create a vector of given length made up of square of the number in DLL file "fc.dll". DLL file is in the zip file enclosed. Put the DLL file in CustomFunctions folder of Prime installation directory. Changing "fc.c" to create a square matrix with values on the diagonal is trivial so not done.
// fc.c : Defines the entry point for the DLL application.
#include "MCADINCL.H"
#include <math.h>
#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"
};
// this code executes the multiplication
// see the information of MathcadUserFunction
// to find out more
LRESULT ExpandRealScalar(COMPLEXARRAY* const Product,
LPCCOMPLEXSCALAR Scalar)
{
unsigned int row, col;
// check that the scalar argument is real
if ((Scalar->imag != 0.0) || (Scalar->real < 1.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
// allocate memory for the product
if (!MathcadArrayAllocate(Product, floor(Scalar->real), 1,
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 * Scalar->real;
}
// normal return
return 0;
}
// fill out a FUNCTIONINFO structure with
// the information needed for registering the
// function with Mathcad
FUNCTIONINFO fc =
{
// Name by which mathcad will recognize the function
"fc",
// description of "multiply" parameters to be used
// by the Insert Function dialog box
"a",
// description of the function for the Insert Function dialog box
"returns the expansion of real scalar a",
// pointer to the executible code
// i.e. code that should be executed
// when a user types in "fc(a)="
(LPCFUNCTION)ExpandRealScalar,
// multiply(a,M) returns a complex array
COMPLEX_ARRAY,
//fc(a) takes on one arguments
1,
// the first is a complex scalar
{ COMPLEX_SCALAR}
};
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
//
// DLL is attaching to the address space of
// the current process.
//
// register the error message table
// Note, that if your function never returns
// an error -- you do not need to
// register an error message table
if (CreateUserErrorMessageTable(
hModule, NUMBER_OF_ERRORS, myErrorMessageTable))
// and if the errors register OK
// go ahead and
// register user function
CreateUserFunction(hModule, &fc);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#undef INTERRUPTED
#undef INSUFFICIENT_MEMORY
#undef MUST_BE_REAL
#undef NUMBER_OF_ERRORS
Cheers
Terry
Hi,
Function to create a vector of given length made up of square of the number in DLL file "fc.dll". DLL file is in the zip file enclosed. Put the DLL file in CustomFunctions folder of Prime installation directory. Changing "fc.c" to create a square matrix with values on the diagonal is trivial so not done.
// fc.c : Defines the entry point for the DLL application.
#include "MCADINCL.H"
#include <math.h>
#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"
};
// this code executes the multiplication
// see the information of MathcadUserFunction
// to find out more
LRESULT ExpandRealScalar(COMPLEXARRAY* const Product,
LPCCOMPLEXSCALAR Scalar)
{
unsigned int row, col;
// check that the scalar argument is real
if ((Scalar->imag != 0.0) || (Scalar->real < 1.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
// allocate memory for the product
if (!MathcadArrayAllocate(Product, floor(Scalar->real), 1,
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 * Scalar->real;
}
// normal return
return 0;
}
// fill out a FUNCTIONINFO structure with
// the information needed for registering the
// function with Mathcad
FUNCTIONINFO fc =
{
// Name by which mathcad will recognize the function
"fc",
// description of "multiply" parameters to be used
// by the Insert Function dialog box
"a",
// description of the function for the Insert Function dialog box
"returns the expansion of real scalar a",
// pointer to the executible code
// i.e. code that should be executed
// when a user types in "fc(a)="
(LPCFUNCTION)ExpandRealScalar,
// multiply(a,M) returns a complex array
COMPLEX_ARRAY,
//fc(a) takes on one arguments
1,
// the first is a complex scalar
{ COMPLEX_SCALAR}
};
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
//
// DLL is attaching to the address space of
// the current process.
//
// register the error message table
// Note, that if your function never returns
// an error -- you do not need to
// register an error message table
if (CreateUserErrorMessageTable(
hModule, NUMBER_OF_ERRORS, myErrorMessageTable))
// and if the errors register OK
// go ahead and
// register user function
CreateUserFunction(hModule, &fc);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#undef INTERRUPTED
#undef INSUFFICIENT_MEMORY
#undef MUST_BE_REAL
#undef NUMBER_OF_ERRORS
Cheers
Terry
Hello @DM_10631844,
It looks like you have a response from a community member. If it helped you solve your question please mark the reply as the Accepted Solution.
Of course, if you have more to share on your issue, please let the Community know so other community members can continue to help you.
Thanks,
Vivek N.
Community Moderation Team.
Perfect thank you I have a question @terryhendicott you did it by command promp or by the visual studio program, I comment that I still do not understand how it would be to try to compile it by the visual studio program, by command it works well but I think that by program I do not add well the references etc if or I start from 0 can you indicate how it would be without the command promp thank you greetings
I compile by Borland C++ Builder 12 - paid for or Visual Studio Community 2022 - free. Both use an IDE to make compilation easier. I have used these so much have forgotten how to use the command line. Using a "*c" file forces c compilation not c++.
Four things to set are:
1) Directory for include of C:\Program Files\PTC\Mathcad Prime 10.0.0.0\Custom Functions
2) #include "MCADINCL.H" in the source file *.c for the dll
3) Directory for library C:\Program Files\PTC\Mathcad Prime 10.0.0.0\Custom Functions
4) Inclusiion of the library mcaduser.lib
5) I turn off wide character strings (optional)
1,3,4,5 are set by options in Project Properties in the IDE (Integrated Development Environment)
2 is in the source file.
Cheers
Terry
This is a project that I have but I would like to compile it in visual studio because with commands if I understand there are some of the steps you mention that have not worked for me
@terryhendicott
Hi,
Prime is a 64 bit program so needs 64 bit DLL's
Need to compile as c code so highlight file in solution explorer and right click and select rename file option
Get rid of precompiled headers
You need to explicitly call up the library to use it
I also set the include and library directories to the original location of the header and library files. It is the same directory. I see you copied them into the solution directory. so no real need to set the directories
Cheers
Terry
Hi,
You change the properties like precompiled headers from the properties dialog launched like this:
Has the function worked? What are the input variables of geometriavolcar as you compiled it please show in mathcad the example as it is solved
Al entrar me aparece esto en el archivo log Exception data:
System.AccessViolationException: Intento de leer o escribir en la memoria protegida. A menudo, esto indica que hay otra memoria dañada.
en Efi.User.Function.Invoke4(Object arg1, Object arg2, Object arg3, Object arg4)
en $$b_706914c0(Object[] , Object )
en Mpl.Run.UnaryDelegateFunction.app[R,A](R& r, A aa)
en Mpl.Run.Function.Call_1[R,A](A aa)
en McdTranslator.values.op_eval(Object )
en $$a_70691364(Object[] , Object )
en Mpl.Run.UnaryDelegateFunction.app[R,A](R& r, A aa)
en Mpl.Run.Function.Call_1[R,A](A aa)
en McdTranslator.values.op_eval(Object )
en Update(Object[] , Object[] , Object[] )
en depman.SafeRun.Run()
en System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
en System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
en System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
en System.Threading.ThreadHelper.ThreadStart()
Hi
Function fc a c language function in this thread works OK. It was written by me so I can debug it easily.
Function geometria_volcar was written by someone else so it would take a long time to debug as it does not work with inputs as per your example.
Start a new thread as this one is months old.
Cheers
Terry
Greetings thanks
Hi
Back to your original post. Swap the indices into the matrix. Mathcad stores arrays in column major format.
No array[ row ][ col ]
Yes array[ col ][ row ]
How would this example be for a custom function with c++?
Great, thank you very much. Now I have another question. In the case of doing operations with sqrt, I had to use Newton Rapson's method. Is there another way? Could you tell me what the error is here for which it doesn't work for me? What happens is that this error always appears. I have not managed to make a good code, and also when I make a mistake, something I am not doing right.
The idea was to pass the code from matlab to mathcad through the custom function c
In the file I put the following functions, is it possible to do the same with units or only that way?