cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Learn all about PTC Community Badges. Engage with PTC and see how many you can earn! X

Custom Functions in Mathcad Prime 3.0

VladimirN
24-Ruby II

Custom Functions in Mathcad Prime 3.0

Using Visual Studio 2010 to build Custom Functions in Mathcad Prime 3.0.

24 REPLIES 24
Hum
7-Bedrock
7-Bedrock
(To:VladimirN)

Wow, I'm a re-entry EE student in Santa Cruz, had no idea this was possible. Thank you good Sir.  

Fred_Kohlhepp
23-Emerald I
(To:Hum)


@Hum wrote:

Wow, I'm a re-entry EE student in Santa Cruz, had no idea this was possible. Thank you good Sir.  


Be careful!  Note that the post you're replying to was put up in 2013, it's almost six years old.  In that time Prime has progress from 3 to 3.1, 4, and 5.  with not a whole lot of improvement--it's still not capable of some of the things that the last pre-Prime version had.

 

Before you spend a lot of time developing new code for Prime review the dialogs on this site about the development progress and speculation about Mathcad's future.  As much as it pains me to say it, your efforts might better be put in another software.  Smath (for one) is a free open software mathcad look-alike that welcomes additions and improvements.  There are others, including some MatLab free clones

 
 
 
 
 
 
Have you compiled any DLLs in Visual Studio 2017? I'm looking for some help stepping through the process.
Hum
7-Bedrock
7-Bedrock
(To:DonDotson)

I am a programing noob really. It is an aspiration of mine though but I haven't taken a stab at exercising this Prime functionality yet. I thought everything was there to work through an example in the zip given. Don't they have you compile their example?

The sMath gentleman are well accomplished and impress me with all of the things they do and how active they are. Here is a thread I started on the sMath forum 9 months ago after trying to use it for my Magnetism course for a few months. 

https://en.smath.com/forum/yaf_postsm57463_sMath-s-competition.aspx#post57463

The gist of it is that it didn't work for me. I concede, It is capable, I just am not with it. I can't do the simplest thing and I really don't feel like being on the forum every time I have a woe with the syntax which invariably impeded everything I tried to accomplish with it, even the most rudimentary of things. That is in contrast to what they can do. Just look at post #31. Amazing to me as an EE student. 

I however had to abandon sMath for Prime for the time being because usability for me comes more naturally in Prime for some reason. Much less consternation... I will likely give it another go though because the annual subscription model for Prime is positively untenable. Divesting from PTC before I become dependent on forever leasing my worksheets from them is probably in my best interest. 

Fred_Kohlhepp
23-Emerald I
(To:Hum)


@Hum wrote:

The sMath gentleman are well accomplished and impress me with all of the things they do and how active they are. Here is a thread I started on the sMath forum 9 months ago after trying to use it for my Magnetism course for a few months. 

https://en.smath.com/forum/yaf_postsm57463_sMath-s-competition.aspx#post57463

The gist of it is that it didn't work for me. I concede, It is capable, I just am not with it. I can't do the simplest thing and I really don't feel like being on the forum every time I have a woe with the syntax which invariably impeded everything I tried to accomplish with it, even the most rudimentary of things. That is in contrast to what they can do. Just look at post #31. Amazing to me as an EE student. 

I however had to abandon sMath for Prime for the time being because usability for me comes more naturally in Prime for some reason. Much less consternation... I will likely give it another go though because the annual subscription model for Prime is positively untenable. Divesting from PTC before I become dependent on forever leasing my worksheets from them is probably in my best interest. 


I agree that SMath is different from Mathcad.  Mathcad comes as a "complete package" and adding to that package requires some serious programming bones; but there's almost no reason to go to that extreme--the capabilities in Mathcad (before Prime at least) were extensive.  SMath is different; it's a bare bones interface.  But it has a large, growing, active community supporting it.  There are a lot of "packages" that add capability, you need to search them out and use them.  An example:

Capture.PNG

My company is heavily committed to Mathcad and I don't think it would be economical for us to switch. I downloaded the Visual Studio solution from VladimirN and compiled it in VS2017 and it worked perfectly. Thank you VladimirN! I think I have what I need to develop DLLs in C++ now using VladimirN's solution as a template.

 

I'm also looking at writing a C++ DLL that calls Fortran subroutines for the math crunching. Fortran is easier for us than C++. Any examples on how we could do that?

Is it possible to create a wrapper other so that code written in C# can be complied to a custom function? Im not well vrsed in C++ and would prefer not to learn anotehr lanaguge as complicated as C++.......

 

 

 

DonDotson
4-Participant
(To:tslewis)

I'm not sure. The easiest thing to do may be to keep the initial C front end and write a subroutine in C# as a static library. I'm basically wanting to do the same think using Fortran. I'm experimenting with that now.

LucMeekes
23-Emerald III
(To:DonDotson)

What type/kind of custom functions are you planning to write for Mathcad?

Bear in mind that the only items you can communicate between Mathcad and your custom function is:

- (0D) Scalars, (1D) Array and (2D) Matrices of ordinary and/or complex numbers,

- Strings

That is: arrays or matrices of strings are NOT supported, nested arrays or matrices are NOT supported, functions are NOT supported. I can can get some of those to work (In Mathcad 11) in some ways, but it is not supported and sometimes functions that try to use unsupported stuff will just crash Mathcad. I have virtually NO experience with Prime, but it is supposed to work like wise.

Given the above + the fact that C# is an interpreted language I see no benefit in using C# for custom functions.

I have my doubts about a static library, or do you mean a C# library that is static with respect to the (C or C++) DLL?

 

Success!

Luc

DonDotson
4-Participant
(To:LucMeekes)

I think C# can be compiled and used to create a DLL:

 

https://www.c-sharpcorner.com/UploadFile/1e050f/creating-and-using-dll-class-library-in-C-Sharp/

 

I'm not particularly interested in it, since C++ and Fortran are perfectly fine for numerical computations. I was just responding to someone that was asking about it because they weren't as familiar with C++

Hum
7-Bedrock
7-Bedrock
(To:DonDotson)

Thank you for the link Sir. They don't teach us Fortran and it was an option to learn Java or C with the University encouraging Java so that's what I did. Now they are currently restructuring the programming foundation away from Java to Python. 

I had to take an online class in my spare time to get an introduction to C# so that is what I would use also if it works. Thanks for the link but PTC makes it seem like not all .Net languages will do it, which I don't really understand because I though at the end of the day they executed equivalently and one could even write various methods of a single program in varying .net languages.

http://support.ptc.com/help/mathcad/en/index.html#page/PTC_Mathcad_Help%2Fabout_custom_functions.html%23

I had found the following link but it looks as if it were something used with an old Mathcad script which the other gentleman says Prime doesn't have so I'm unsure if it is worth my time to try and slog through and translate into my own purposefulness...

https://community.ptc.com/t5/PTC-Mathcad/Call-C-Object-from-MathCad/m-p/241807

JeffH1
14-Alexandrite
(To:DonDotson)

I've done it, however my code is proprietary and I can't share the example.

 

There are two routes:

Compile the Fortran into a stand-alone DLL.  Load and call the DLL from a Mathcad DLL written in C++.  Check Google on how to do this.  Lots of programming forums will show you how.  This makes a smaller Mathcad Add-in since the Fortran DLL is just getting loaded and called in memory.

Compile the Fortran into an object library (LIB) and link the function routines in as EXTERN routines in your Mathcad DLL written in C++.  Makes a bigger DLL as the Fortran is actually linked into the DLL.

Either way works and I haven't really seen a speed difference.  Route 2 might be easier from a mixed-language programming perspective.  It will take some work an research, but Stack Overflow is your friend!

DonDotson
4-Participant
(To:JeffH1)

Thanks, I think my strategy is going to be the second way: Compile the Fortran into an object library (LIB) and link the function routines in as EXTERN routines in your Mathcad DLL written in C++.  I'll give it a try and let you know how it goes.

There are a lot of deal breakign isses with Smath:

  • The amount of stand alone file I/O functions is extremely limited
  • The Excel plug in to read files is very limited and is dependent on it being maintained by the developer
  • No avbility to change any fonts
  • No labels
  • Cannot  copy math and text resgions to word or RTF - it will just copy a non formattable/edtable image
  • Cannot change size of images pasted in to document
  • Text regions are also formatted with an exterior boundary
  • No filterNan operations on matrices/vectors
  • Cannot appear to reference worksheets
Hum
7-Bedrock
7-Bedrock
(To:tslewis)

Have you tried mentioning any of these perceived inabilities to the sMath guys in their forum. I wouldn't be surprised if they immediately furnish you with work arounds for half of the things on your list. From my experience they can indeed work the seemingly impossible more often then not. 

Yes, I have 33 plug-ins installed on my sMath and I've downloaded almost 100 examples from various posts on their forums. Still, my first attempt at becoming proficient with it was unfruitful. 

 

Are you suggesting that developing sMath plug-ins is a more tactful route to take as opposed to developing custom functions for Prime? I don't even know what I would be interested in writing for either but was just surprised that Prime had this functionality considering it gets a lot of flak in general. Custom functions are a measure of reprieve for all those lamenting the myriad shortcomings of Prime aren't they? I am not asking rhetorically. I am a student and genuinely may be confusing the measure of promise a custom Prime function provides. 

 

Considering it took 6 years for someone to comment on this thread, and a comparative laymen at that, I might assume there is not much promise in it since there is a dearth of people utilizing the provision, or at least posting about it. 

DonDotson
4-Participant
(To:Hum)

Just for my two cents, Mathcad is pretty cheap for commercial software and it fits my company's needs. In many ways, Prime isn't as good as 15, but 5.0 was a significant improvement. We're pretty happy with it. I'm just looking for more help to write custom functions.
Fred_Kohlhepp
23-Emerald I
(To:Hum)


@Hum wrote:

Yes, I have 33 plug-ins installed on my sMath and I've downloaded almost 100 examples from various posts on their forums. Still, my first attempt at becoming proficient with it was unfruitful. 

 

Are you suggesting that developing sMath plug-ins is a more tactful route to take as opposed to developing custom functions for Prime? I don't even know what I would be interested in writing for either but was just surprised that Prime had this functionality considering it gets a lot of flak in general. Custom functions are a measure of reprieve for all those lamenting the myriad shortcomings of Prime aren't they? I am not asking rhetorically. I am a student and genuinely may be confusing the measure of promise a custom Prime function provides. 

 

Considering it took 6 years for someone to comment on this thread, and a comparative laymen at that, I might assume there is not much promise in it since there is a dearth of people utilizing the provision, or at least posting about it. 


I don't know if anyone has successfully written a custom function in Prime.  There were a number of people writing scripts in Mathcad, but Prime doesn't support scripts (and a lot of other things.)

 

The rate of development in Prime combined with the annual license fees have managed to drive many of the long-term users and supporters to alternative methods.  If I were beginning a career I would rather put effort into a platform that is supported and growing rather than a "mature" platform that is no longer being supported.

JeffH1
14-Alexandrite
(To:Fred_Kohlhepp)

I have written several Add-ins (Custom Functions) and successfully re-compiled them for Prime.  There is no code modification required from the Mathcad 15 version; the original C/C++ code just gets compiled to a 64-bit DLL (instead of 32-bit) and linked with the new Prime mcaduser.lib library (using MCADINCL.H) and voila!  The only shortcoming is that Mathcad 15 allowed you to create an XML file that put the functions and descriptions in the Function Panel in the user interface.  Prime, sadly does not.  You have to have an external reference.

 

For successful examples of add-ins for both 15 and Prime, see:

DonDotson
4-Participant
(To:JeffH1)

See the attached code. If you wanted to move the subtraction from the 'realsum' routine to a Fortran subroutine, what would you write?

 

 

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "mcadincl.h"
    
    extern FUNCTIONINFO realsum, realsub;
    
    
    char *ErrorMessageTable[] = {
    "argument must be real",    //  error 1 --  argument must be real
    "insufficient memory",      //  error 2 --  memory allocation error
    "interrupted"               //  error 3 --  execution interrupted
    };

//BOOL WINAPI _CRT_INIT(HMODULE hModule, DWORD dwReason, LPVOID lpReserved);

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.
      //
     //   if (!_CRT_INIT(hModule, ul_reason_for_call, lpReserved)) {
    //        return FALSE;
    //    }

        if (!CreateUserErrorMessageTable( hModule, 3, ErrorMessageTable ) )
            break;
        
        if ( CreateUserFunction( hModule, &realsum ) == NULL )
            break;
                        

		CreateUserFunction( hModule, &realsub);
		break;
		}
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

 

// realsub function
#include "StdAfx.h"
#include "mcadincl.h"

LRESULT realsubFunction(LPCOMPLEXSCALAR     c,
	LPCCOMPLEXSCALAR    a,
	LPCCOMPLEXSCALAR    b);

FUNCTIONINFO    realsub =
{
"realsub",                          // Name by which mathcad will recognize the function
"a,b",                              // realsub will be called as realsub(a,b)
"real sum of scalars a and b",      // description of realsub(a,b)
(LPCFUNCTION)realsubFunction,       // pointer to the executible code
COMPLEX_SCALAR,                     // the return type is also a complex scalar
2,                                  //  the function takes on 2 arguments
{ COMPLEX_SCALAR, COMPLEX_SCALAR}   // both arguments are complex scalars
};


LRESULT realsubFunction(LPCOMPLEXSCALAR     c,
	LPCCOMPLEXSCALAR    a,
	LPCCOMPLEXSCALAR    b)
{

	// first check to make sure
	// a has no imaginary component

	if (a->imag != 0.0)
		return MAKELRESULT(1, 1);

	if (b->imag != 0.0)
		return MAKELRESULT(1, 2);

	// otherwise, all is well so add a and b
	c->real = a->real - b->real;	//-> is used to access a member of a struct which is referenced
									// by the pointer in question


	return 0;               // return 0 to indicate there was no error

}

JeffH1
14-Alexandrite
(To:DonDotson)

So, each Fortran routine needs a C stub function.  That way the main DLL function can call a C routine and we leave all the external Fortran acrobatics in the stub functions.  I would take the #include stdafx.h out of both files, it won't hurt, but you don't need it.   I don't include it in any of my Mathcad DLLs.

 

Create realsum.f or realsum.f90 and compile it to a Fortran library (.LIB) file.  If you have multiple Fortran functions, you can compile them all into one .LIB file.  I usually make my Fortran functions/subroutines upper-case, something like function REALSUM(a, b, c).  This helps me keep track of which is the Fortran function and which is the C stub function.  Make sure the first thing your Fortran routine does is Type Cast the parameters,

 

double precision a, b, c

 

You still need realsum.c below as it becomes the C stub function that calls the Fortran.

 

At the top of realsum.c file, but after #include "mcadincl.h", tell the code that you are going to use an external function that doesn't return a value directly (void).

 

  extern void REALSUM( double *a, double *b, double *c );

These are passed by reference so that the Fortran can modify the memory space and change the value of c.

 

In the function xxx, create a place holder variable for the return value:

LRESULT realsubFunction(LPCOMPLEXSCALAR     c,
	LPCCOMPLEXSCALAR    a,
	LPCCOMPLEXSCALAR    b)
{
double ret;
...

Then, instead of actually doing the calculation, replace the following lines

	// otherwise, all is well so add a and b
	c->real = a->real - b->real;	//-> is used to access a member of a struct which is referenced
									// by the pointer in question

with the call to the external Fortran routine...

	// otherwise, all is well so add a and b
double aval = a->real; // save the inputs in a variable we can reference
double bval = b->real; // -> is used to access a member of a struct which is referenced
// by the pointer in question
REALSUM( &aval, &bval, &ret ); // This calls the Fortran and loads the return value c->real = ret; // put the return value into the c->real struct

I don't know if you can directly call

        REALSUM( &a->real, &b->real, &c->real );

Seems risky.  I always make temp variables and make the Fortran call with those.

 

When you compile your Mathcad DLL with the C compiler, make sure that you include both .c routines in the compile step and your Fortran library in the link step.  The linker will be looking for the external Fortran routines.

 

I think that should do it.  Good luck.  Again, if something doesn't work out, https://stackoverflow.com is your friend.  Here's another useful link from LLNL: Using C/C++ and Fortran together.

Regarding Prime's future, it looks like PTC is officially at the end of its "roadmap":

https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=2ahUKEwingLfpt7DiAhV0JTQIHTm1BK4QFjABegQIBRAC&url=https%3A%2F%2Fcommunity.ptc.com%2Fsejnu66972%2Fattachments%2Fsejnu66972%2FPTCMathcad%2F175669%2F2%2FPTC%2520Mathcad%2520Roadmap_2016.pdf.pdf&usg=AOvVaw3elaXhtRgtCa4WwrnzwusX

Have a look at page 14. The roadmap ends at version 5.0. It may not be that meaningful but it does kind of send a message to users that it now seems to be officially on PTC's back burner. They even called the present version 5.0.0 seeming to further indicate only the most incremental of bug fixes for some time. 

 

DonDotson
4-Participant
(To:VladimirN)

VladimirN, I downloaded your user-efi-dev-studio-project, compiled it and it ran perfectly in Prime 5.0. Have you created any more DLLs for Prime? Also, have you used any mixed languages such as Fortran?

Top Tags