I am trying to set up a connection between Visual Studio 10 and Mathematica 8.0 on a Windows system. I found several sources of information on the Wolfram website, but I get entirely lost. Most of the info deals with calling C++ functions from within Mathematica, but I would like it the other way round. I have quite a lot of functionality in my C++ code and I just call Mathematica to make some integral calculations.
Is there a good step-by-step approach to set up this connection? What files should I include in my project? What settings need to be changed? Does anyone have a complete example of pieces of code that gives insights in the general approach? That would be a great help.
I followed the standard instructions to add the lib
, bin
and include
to the Visual Studio directories. More specifically, I was also wondering whether in this case I also need to make a .tm
file? Should it be empty then? The example here looks very clear, but this is approached from a Linux/Mac perspective.
I hope someone could bring me some guidance.
Taking into account your suggestions, I have developed the following program, but there seems to be a problem with retrieving the packages. I have put the entire code here.
The program first sends some variables to Mathematica kernel and then it should perform the integral calculation. I am only interested in the final payoff that is calculated by Mathematica. While debugging, it seems to be that the program gets stuck in the removal of all the packages (in the loop just after sending the integral function). There is no problem with the function, I guess, because it performs the calculation perfectly when I just use Mathematica.
#include
#include
#include "mathlink.h"
static void init_and_openlink( int argc, char* argv[]);
static void error( MLINK lp);
MLENV ep = (MLENV)0;
MLINK lp = (MLINK)0;
int main(int argc, char* argv[]){
int pkt;
float payoff;
init_and_openlink( argc, argv);
Now, I send the different parameters and the final function of interest:
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"SetDelayed",2);
MLPutString(lp, "mue");
MLPutReal(lp,0.25);
MLEndPacket(lp);
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"SetDelayed",2);
MLPutString(lp, "mui");
MLPutReal(lp,0.25);
MLEndPacket(lp);
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"SetDelayed",2);
MLPutString(lp, "lambdae");
MLPutReal(lp,0.25);
MLEndPacket(lp);
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"SetDelayed",2);
MLPutString(lp, "lambdai");
MLPutReal(lp,0.25);
MLEndPacket(lp);
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"SetDelayed",2);
MLPutString(lp, "sigmap");
MLPutReal(lp,0.05);
MLEndPacket(lp);
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"SetDelayed",2);
MLPutString(lp, "betae");
MLPutReal(lp,0.05);
MLEndPacket(lp);
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"SetDelayed",2);
MLPutString(lp, "betai");
MLPutReal(lp,0.05);
MLEndPacket(lp);
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"SetDelayed",2);
MLPutString(lp, "gammae");
MLPutReal(lp,0.05);
MLEndPacket(lp);
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"SetDelayed",2);
MLPutString(lp, "gammai");
MLPutReal(lp,0.10);
MLEndPacket(lp);
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"SetDelayed",2);
MLPutString(lp, "d");
MLPutReal(lp,0.2);
MLEndPacket(lp);
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"SetDelayed",2);
MLPutString(lp, "experience1");
MLPutInteger(lp,2);
MLEndPacket(lp);
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"SetDelayed",2);
MLPutString(lp, "experience2");
MLPutInteger(lp,3);
MLEndPacket(lp);
MLPutFunction( lp,"EnterTextPacket",1);
MLPutString(lp,"expectedpayoff1bis[i1_, b1_,i2_,b2_] := NIntegrate[PDF[NormalDistribution[(1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1]))*(1 + b1/100), (1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1]))*(1 + b1/100)* Sqrt[sigmap^2 + (gammae*Exp[-lambdae*experience1])^2 + (gammai*Exp[-lambdai*i1])^2]], x]*(1 - CDF[NormalDistribution[(1 + betae*Exp[-mue*experience2] + betai*Exp[-mui*i2])*(1 + b2/100), (1 + betae*Exp[-mue*experience2] + betai*Exp[-mui*i2])*(1 + b2/100)*Sqrt[sigmap^2 + (gammae*Exp[-lambdae*experience2])^2 + (gammai*Exp[-lambdai*i2])^2]], x]), {x, 0, 2}]*(NIntegrate[(x*PDF[NormalDistribution[(1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1]))*(1 + b1/100), (1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1]))*(1 + b1/100)* Sqrt[sigmap^2 + (gammae*Exp[-lambdae*experience1])^2 + (gammai*Exp[-lambdai*i1])^2]], x]*(1 - CDF[NormalDistribution[(1 + betae*Exp[-mue*experience2] + betai*Exp[-mui*i2])*(1 + b2/100), (1 + betae*Exp[-mue*experience2] + betai*Exp[-mui*i2])*(1 + b2/100)*Sqrt[sigmap^2 + (gammae*Exp[-lambdae*experience2])^2 + (gammai*Exp[-lambdai*i2])^2]], x])/NIntegrate[PDF[NormalDistribution[(1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1]))*(1 + b1/100), (1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1]))*(1 + b1/100)*Sqrt[sigmap^2 + (gammae*Exp[-lambdae*experience1])^2 + (gammai*Exp[-lambdai*i1])^2]], x]*(1 - CDF[NormalDistribution[(1 + betae*Exp[-mue*experience2] +betai*Exp[-mui*i2])*(1 + b2/100), (1 + betae*Exp[-mue*experience2] + betai*Exp[-mui*i2])*(1 + b2/100)*Sqrt[sigmap^2 + (gammae*Exp[-lambdae*experience2])^2 + (gammai*Exp[-lambdai*i2])^2]], x]), {x, 0, 2}]), {x, 0, 2}] - (1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1])) - d*i1/100) - (1 - d)*i1/100");
MLEndPacket(lp);
I don't need any of the information retrieved from the above packages, so I try to get rid of everything. This is were the debugging is in a loop (When I pause the debugging, I get the screen with "no source available".
while ((pkt=MLNextPacket(lp),pkt)&&pkt!=RETURNPKT) {
MLNewPacket(lp);
if (MLError(lp)) error(lp);
}
MLNewPacket(lp);
Afterwards I want to evaluate the function and the result needs to be printed on the screen. This is the only output I am interested in:
MLPutFunction( lp,"EnterExpressionPacket",1);
MLPutFunction(lp,"expectedpayoff1bis",4);
MLPutInteger(lp,2);
MLPutInteger(lp,10);
MLPutInteger(lp,4);
MLPutInteger(lp,12);
MLEndPacket(lp);
while( (pkt = MLNextPacket( lp), pkt) && pkt != RETURNPKT) {
MLNewPacket( lp);
if (MLError( lp)) error( lp);
}
MLGetReal( lp,&payoff);
printf( "payoff: %f", payoff);
MLPutFunction( lp, "Exit", 0);
return 0;
}
The rest of the code is retrieved from the examples
static void error( MLINK lp){
if( MLError( lp)){
fprintf( stderr, "Error detected by MathLink: %s.\n",MLErrorMessage(lp));
}
else{
fprintf( stderr, "Error detected by this program.\n");
}
exit(3);
}
static void deinit( void){
if( ep) MLDeinitialize( ep);
}
static void closelink( void){
if( lp) MLClose( lp);
}
static void init_and_openlink( int argc, char* argv[]){
#if MLINTERFACE >= 3
int err;
#else
long err;
#endif /* MLINTERFACE >= 3 */
ep = MLInitialize( (MLParametersPointer)0);
if( ep == (MLENV)0) exit(1);
atexit( deinit);
#if MLINTERFACE < 3
lp = MLOpenArgv( ep, argv, argv + argc, &err);
#else
lp = MLOpenArgcArgv( ep, argc, argv, &err);
#endif
if(lp == (MLINK)0) exit(2);
atexit( closelink);
}
Answer
There are a few problems with your code. If you fix those up, as I did, your program will run fine.
First off, the reason you see "no source available" when you pause the program is probably that when you break, the program is down inside a MathLink function, and so it is complaining that it doesn't have access to the MathLink library source code. To debug your program, you generally set breakpoints in your code and step through it, and not try break in at an arbitrary time, which often will be inside some library that you did not write.
Back to the code. The most glaring error is that you send a bunch of evaluations to the kernel, but fail to read the packets that come back from each one. When you go to read what you think is your final result, you will actually be reading some earlier result that you never drained off the link. Every interaction with Mathematica will involve you sending a packet and then immediately draining off all the packets that come back. You will note that in my program I have written a discardResult()
function that drains all packets up to, and including, the ReturnPacket
containing the ignored result.
Don't use EnterExpressionPacket
as the packet when sending things to the kernel. This engages the whole main loop, including assignment of In/Out, etc., and you get a different sequence of packets coming back. Better to use EvaluatePacket
, from which you are guaranteed to get back a single ReturnPacket
containing the result (you might also get other packets along the way, such as for messages and Print
output).
Another error is that you are using MLPutString()
to send your symbol names (mue, mui, lambdae, etc.) These are symbols, so use MLPutSymbol()
.
I also changed your use of SetDelayed
to Set
, just to be picky.
You used EnterTextPacket
for the definition of expectedpayoff1bis
so that you could send it as a string. Like EnterExpressionPacket
, EnterTextPacket
engages the main loop, and gives a different packet sequence in return, so avoid it. The best way to send Mathematica input in textual format is to use EvaluatePacket[ToExpression["string of code"]]
.
Here is my modified version of your program. It runs and gives a numerical answer for me.
#include
#include
#include "mathlink.h"
static void init_and_openlink( int argc, char* argv[]);
static void error( MLINK lp);
static void discardResult(MLINK lp);
MLENV ep = (MLENV)0;
MLINK lp = (MLINK)0;
int main(int argc, char* argv[])
{
int pkt;
double payoff;
init_and_openlink( argc, argv);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"Set",2);
MLPutSymbol(lp, "mue");
MLPutReal(lp,0.25);
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"Set",2);
MLPutSymbol(lp, "mui");
MLPutReal(lp,0.25);
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"Set",2);
MLPutSymbol(lp, "lambdae");
MLPutReal(lp,0.25);
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"Set",2);
MLPutSymbol(lp, "lambdai");
MLPutReal(lp,0.25);
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"Set",2);
MLPutSymbol(lp, "sigmap");
MLPutReal(lp,0.05);
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"Set",2);
MLPutSymbol(lp, "betae");
MLPutReal(lp,0.05);
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"Set",2);
MLPutSymbol(lp, "betai");
MLPutReal(lp,0.05);
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"Set",2);
MLPutSymbol(lp, "gammae");
MLPutReal(lp,0.05);
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"Set",2);
MLPutSymbol(lp, "gammai");
MLPutReal(lp,0.10);
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"Set",2);
MLPutSymbol(lp, "d");
MLPutReal(lp,0.2);
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"Set",2);
MLPutSymbol(lp, "experience1");
MLPutInteger(lp,2);
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"Set",2);
MLPutSymbol(lp, "experience2");
MLPutInteger(lp,3);
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction( lp,"ToExpression",1);
MLPutString(lp,"expectedpayoff1bis[i1_, b1_,i2_,b2_] := NIntegrate[PDF[NormalDistribution[(1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1]))*(1 + b1/100), (1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1]))*(1 + b1/100)* Sqrt[sigmap^2 + (gammae*Exp[-lambdae*experience1])^2 + (gammai*Exp[-lambdai*i1])^2]], x]*(1 - CDF[NormalDistribution[(1 + betae*Exp[-mue*experience2] + betai*Exp[-mui*i2])*(1 + b2/100), (1 + betae*Exp[-mue*experience2] + betai*Exp[-mui*i2])*(1 + b2/100)*Sqrt[sigmap^2 + (gammae*Exp[-lambdae*experience2])^2 + (gammai*Exp[-lambdai*i2])^2]], x]), {x, 0, 2}]*(NIntegrate[(x*PDF[NormalDistribution[(1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1]))*(1 + b1/100), (1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1]))*(1 + b1/100)* Sqrt[sigmap^2 + (gammae*Exp[-lambdae*experience1])^2 + (gammai*Exp[-lambdai*i1])^2]], x]*(1 - CDF[NormalDistribution[(1 + betae*Exp[-mue*experience2] + betai*Exp[-mui*i2])*(1 + b2/100), (1 + betae*Exp[-mue*experience2] + betai*Exp[-mui*i2])*(1 + b2/100)*Sqrt[sigmap^2 + (gammae*Exp[-lambdae*experience2])^2 + (gammai*Exp[-lambdai*i2])^2]], x])/NIntegrate[PDF[NormalDistribution[(1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1]))*(1 + b1/100), (1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1]))*(1 + b1/100)*Sqrt[sigmap^2 + (gammae*Exp[-lambdae*experience1])^2 + (gammai*Exp[-lambdai*i1])^2]], x]*(1 - CDF[NormalDistribution[(1 + betae*Exp[-mue*experience2] +betai*Exp[-mui*i2])*(1 + b2/100), (1 + betae*Exp[-mue*experience2] + betai*Exp[-mui*i2])*(1 + b2/100)*Sqrt[sigmap^2 + (gammae*Exp[-lambdae*experience2])^2 + (gammai*Exp[-lambdai*i2])^2]], x]), {x, 0, 2}]), {x, 0, 2}] - (1 + (betae*Exp[-mue*experience1] + betai*Exp[-mui*i1])) - d*i1/100) - (1 - d)*i1/100");
MLEndPacket(lp);
discardResult(lp);
MLPutFunction( lp,"EvaluatePacket",1);
MLPutFunction(lp,"expectedpayoff1bis",4);
MLPutInteger(lp,2);
MLPutInteger(lp,10);
MLPutInteger(lp,4);
MLPutInteger(lp,12);
MLEndPacket(lp);
while( (pkt = MLNextPacket( lp), pkt) && pkt != RETURNPKT) {
MLNewPacket( lp);
if (MLError( lp)) error( lp);
}
MLGetReal( lp,&payoff);
printf( "payoff: %f", payoff);
return 0;
}
static void discardResult(MLINK lp) {
int pkt;
while( (pkt = MLNextPacket( lp), pkt) && pkt != RETURNPKT) {
MLNewPacket( lp);
if (MLError( lp)) error( lp);
}
MLNewPacket(lp);
}
static void error( MLINK lp){
if( MLError( lp)){
fprintf( stderr, "Error detected by MathLink: %s.\n",MLErrorMessage(lp));
}
else{
fprintf( stderr, "Error detected by this program.\n");
}
exit(3);
}
static void deinit( void){
if( ep) MLDeinitialize( ep);
}
static void closelink( void){
if( lp) MLClose( lp);
}
static void init_and_openlink( int argc, char* argv[]){
#if MLINTERFACE >= 3
int err;
#else
long err;
#endif /* MLINTERFACE >= 3 */
ep = MLInitialize( (MLParametersPointer)0);
if( ep == (MLENV)0) exit(1);
atexit( deinit);
#if MLINTERFACE < 3
lp = MLOpenArgv( ep, argv, argv + argc, &err);
#else
lp = MLOpenArgcArgv( ep, argc, argv, &err);
#endif
if(lp == (MLINK)0) exit(2);
atexit( closelink);
}
Comments
Post a Comment