#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <fstream>

#include "sopnamsp.h"
#include "tarrinit.h"
#include "array.h"

#include "pdlmgr.h"
#include "pexceptions.h"
#include "timing.h"

// Fonction de test qu'on reproduit dans le fichier CTestFileName
double testfunc_dynl(double x, double y)
{
  return (exp(-x)+sin(y)*x);
}

typedef double (* MyDlFunctionOfXY) (double x, double y);

int main(int narg, char *arg[])
{
  SophyaInit();
  InitTim();

  if (narg < 3) {
    cout << " --- tdynl -- test de la classe PDynLinkMgr --- \n " 
         << " Usage: tdynl TmpDirName/ CTestFileName\n" 
	 << " Exemple: tdynl /tmp/ toto.c \n" << endl;
   return(0);
  }

  try {
    string TmpDirName = arg[1];
    string CTestFileName = arg[2];
    string cfilename = TmpDirName + CTestFileName;
    {
      ofstream of(cfilename.c_str());
      of << "#include <math.h> \n "
	 << "double myf_dyl(double x, double y) \n"
	 << "{ \n" 
	 << " return (exp(-x)+sin(y)*x); \n"
	 << "} \n" << endl;
      cout << " File " << cfilename << "created ... " << endl;
      }

    cout << " Calling PDynLinkMgr::BuildFromCFile(" << cfilename << ")" << endl;
    PDynLinkMgr::SetTmpDir(TmpDirName);
    PDynLinkMgr * dyl = PDynLinkMgr::BuildFromCFile(cfilename);
    PrtTim(" End of Compile-Link ");
    if (dyl != NULL) {
      MyDlFunctionOfXY f = (MyDlFunctionOfXY)dyl->GetFunction("myf_dyl");  
      if (f != NULL) {
	cout << " DlFunction f dyl.GetFunction(myf_dyl) linked OK - calling f() " << endl;
	cout << "f(0,1)= " << f(0.,1.) << "  ?= testfunc_dynl(0,1)= " << testfunc_dynl(0.,1.) << endl;
	cout << "f(1,1)= " << f(1.,1.) << "  ?= testfunc_dynl(1,1)= " << testfunc_dynl(1.,1.) << endl;
	cout << "f(-1,2.5)= " << f(-1.,2.5) << "  ?= testfunc_dynl(-1,2.5)= " << testfunc_dynl(-1.,2.5) << endl;
      } 
      else {
	cout << " ERROR linking DlFunction f !!! " << endl;
      }
    delete dyl;
    }
    else cout << " ERROR Creating shared object !!! " << endl;
  }
 
  catch (PThrowable & exc) {
    cerr << " Catched Exception " << (string)typeid(exc).name()
         << " - Msg= " << exc.Msg() << endl;
  }
  catch (...) {
    cerr << " some other exception was caught ! " << endl;
  }

  PrtTim(" End of tdynl ");
}
