// Steamtables.c : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "MCADINCL.H"

#ifdef _MANAGED
#pragma managed(push, off)
#endif
HINSTANCE hinstXSteamLib;

// DLL function signatures
typedef double (CALLBACK* oneArgFunctionType)( double );
typedef double (CALLBACK* twoArgFunctionType)( double, double );

oneArgFunctionType oneArgFunction;
twoArgFunctionType twoArgFunction;

oneArgFunctionType oneArgFunctionDllPtr;
twoArgFunctionType twoArgFunctionDllPtr;

char *functionName[40];


LRESULT callOneArgFunction(LPCOMPLEXSCALAR a, LPCCOMPLEXSCALAR b) {
    // Load DLL file
    HINSTANCE hinstXSteamLib = LoadLibrary("XSteam_V2.6b.dll");
    if (hinstXSteamLib == NULL)
    {
        //ERROR: unable to load DLL
        return 1; //report error to mathcad
    }
     
    // Get function pointer
    oneArgFunctionDllPtr = (oneArgFunctionType) GetProcAddress(hinstXSteamLib, *functionName);
    if (oneArgFunctionDllPtr == NULL)
    {
        //ERROR: unable to find DLL function
        FreeLibrary(hinstXSteamLib);
        return 1; //report error to mathcad
    }
    
    // Call function.
    a->real = oneArgFunctionDllPtr( b->real );

    FreeLibrary(hinstXSteamLib);
    return 0; //success
}

LRESULT callTwoArgFunction (   LPCOMPLEXSCALAR     a,
                               LPCCOMPLEXSCALAR    b,  
						       LPCCOMPLEXSCALAR    c   )
{
    // Load DLL file
    HINSTANCE hinstXSteamLib = LoadLibrary("XSteam_V2.6b.dll");
    if (hinstXSteamLib == NULL)
    {
        //ERROR: unable to load DLL
        return 1; //report error to mathcad
    }
     
    // Get function pointer
    twoArgFunctionDllPtr = (twoArgFunctionType) GetProcAddress(hinstXSteamLib, *functionName);
    if (twoArgFunctionDllPtr == NULL)
    {
        //ERROR: unable to find DLL function
        FreeLibrary(hinstXSteamLib);
        return 1; //report error to mathcad
    }
    
    // Call function.
    a->real = twoArgFunctionDllPtr( b->real, c->real );

    FreeLibrary(hinstXSteamLib);
    return 0; //success
}




/*
  Info and proxy to all available functions in the XSteam DLL
*/

LRESULT Tsat_pFunction(  LPCOMPLEXSCALAR     a,  //put return value here
                         LPCCOMPLEXSCALAR    b   )   // 1st argument
{
	*functionName = "Tsat_p@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO Tsat_p = 
{
    "Tsat_p",                           // Name by which mathcad will recognize the function
    "a",                                // how will the argument(s) be called '"a, b"'
    "Saturation temperature",			// description
    (LPCFUNCTION)Tsat_pFunction,        // pointer to the executible code
    COMPLEX_SCALAR,						// the return type
    1,                                  // number of arguments
    { COMPLEX_SCALAR }                  // argument types: '{ COMPLEX_SCALAR, COMPLEX_SCALAR }'
};


LRESULT T_phFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b,  
						LPCCOMPLEXSCALAR    c   )
{
	*functionName = "T_ph@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO T_ph = 
{
    "T_ph",
    "a, b",
    "Temperture as a function of pressure and enthalpy",
    (LPCFUNCTION)T_phFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};


LRESULT T_psFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b,  
						LPCCOMPLEXSCALAR    c   )
{
	*functionName = "T_ps@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO T_ps = 
{
    "T_ps",
    "a, b",
    "Temperture as a function of pressure and entropy",
    (LPCFUNCTION)T_psFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT T_hsFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b,  
						LPCCOMPLEXSCALAR    c   )
{
	*functionName = "T_hs@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO T_hs = 
{
    "T_hs",
    "a, b",
    "Temperture as a function of enthalpy and entropy",
    (LPCFUNCTION)T_hsFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};



LRESULT psat_TFunction(  LPCOMPLEXSCALAR     a,
                         LPCCOMPLEXSCALAR    b   )
{
	*functionName = "psat_T@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO psat_T = 
{
    "psat_T",
    "a",
    "Saturation pressure",
    (LPCFUNCTION)psat_TFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};


LRESULT p_hsFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b,  
						LPCCOMPLEXSCALAR    c   )
{
	*functionName = "p_hs@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO p_hs = 
{
    "p_hs",
    "a, b",
    "Pressure as a function of h and s",
    (LPCFUNCTION)p_hsFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT p_hrhoFunction(   LPCOMPLEXSCALAR     a,
                          LPCCOMPLEXSCALAR    b,  
						  LPCCOMPLEXSCALAR    c   )
{
	*functionName = "p_hrho@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO p_hrho = 
{
    "p_hrho",
    "a, b",
    "Pressure as a function of enthalpy and density",
    (LPCFUNCTION)p_hrhoFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT hV_pFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b   )
{
	*functionName = "hV_p@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO hV_p = 
{
    "hV_p",
    "a",
    "Saturated vapour enthalpy",
    (LPCFUNCTION)hV_pFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT hL_pFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b   )
{
	*functionName = "hL_p@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO hL_p = 
{
    "hL_p",
    "a",
    "Saturated liquid enthalpy",
    (LPCFUNCTION)hL_pFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT hV_TFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b   )
{
	*functionName = "hV_T@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO hV_T = 
{
    "hV_T",
    "a",
    "Saturated vapour enthalpy",
    (LPCFUNCTION)hV_pFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT hL_TFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b   )
{
	*functionName = "hL_T@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO hL_T = 
{
    "hL_T",
    "a",
    "Saturated liquid enthalpy",
    (LPCFUNCTION)hL_TFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT h_pTFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b,  
					    LPCCOMPLEXSCALAR    c   )
{
	*functionName = "h_pT@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO h_pT = 
{
    "h_pT",
    "a, b",
    "Entalpy as a function of pressure and temperature",
    (LPCFUNCTION)h_pTFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT h_psFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b,  
					    LPCCOMPLEXSCALAR    c   )
{
	*functionName = "h_ps@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO h_ps = 
{
    "h_ps",
    "a, b",
    "Entalpy as a function of pressure and entropy",
    (LPCFUNCTION)h_psFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT h_pxFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b,  
					    LPCCOMPLEXSCALAR    c   )
{
	*functionName = "h_px@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO h_px = 
{
    "h_px",
    "a, b",
    "Entalpy as a function of pressure and vapour fraction",
    (LPCFUNCTION)h_pxFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT h_TxFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b,  
					    LPCCOMPLEXSCALAR    c   )
{
	*functionName = "h_Tx@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO h_Tx = 
{
    "h_Tx",
    "a, b",
    "Entalpy as a function of temperature and vapour fraction",
    (LPCFUNCTION)h_TxFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT h_prhoFunction(   LPCOMPLEXSCALAR     a,
                          LPCCOMPLEXSCALAR    b,  
					      LPCCOMPLEXSCALAR    c   )
{
	*functionName = "h_prho@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO h_prho = 
{
    "h_prho",
    "a, b",
    "Entalpy as a function of pressure and density. Observe for low temperatures (liquid) this equation has 2 solutions. (Not valid!!)",
    (LPCFUNCTION)h_prhoFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};


LRESULT vV_pFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b   )
{
	*functionName = "vV_p@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO vV_p = 
{
    "vV_p",
    "a",
    "Saturated vapour volume",
    (LPCFUNCTION)vV_pFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT vL_pFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b   )
{
	*functionName = "vL_p@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO vL_p = 
{
    "vL_p",
    "a",
    "Saturated liquid volume",
    (LPCFUNCTION)vL_pFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT vV_TFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b   )
{
	*functionName = "vV_T@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO vV_T = 
{
    "vV_T",
    "a",
    "Saturated vapour volume",
    (LPCFUNCTION)vV_TFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};


LRESULT v_pTFunction(   LPCOMPLEXSCALAR     a,
                          LPCCOMPLEXSCALAR    b,  
					      LPCCOMPLEXSCALAR    c   )
{
	*functionName = "v_pT@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO v_pT = 
{
    "v_pT",
    "a, b",
    "Specific volume as a function of pressure and temperature.",
    (LPCFUNCTION)v_pTFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT v_phFunction(   LPCOMPLEXSCALAR     a,
                          LPCCOMPLEXSCALAR    b,  
					      LPCCOMPLEXSCALAR    c   )
{
	*functionName = "v_ph@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO v_ph = 
{
    "v_ph",
    "a, b",
    "Specific volume as a function of pressure and enthalpy",
    (LPCFUNCTION)v_phFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT v_psFunction(   LPCOMPLEXSCALAR     a,
                          LPCCOMPLEXSCALAR    b,  
					      LPCCOMPLEXSCALAR    c   )
{
	*functionName = "v_ps@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO v_ps = 
{
    "v_ps",
    "a, b",
    "Specific volume as a function of pressure and entropy.",
    (LPCFUNCTION)v_psFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT vL_TFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b   )
{
	*functionName = "vL_T@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO vL_T = 
{
    "vL_T",
    "a",
    "Saturated liquid volume",
    (LPCFUNCTION)vL_TFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};


LRESULT rhoV_pFunction(   LPCOMPLEXSCALAR     a,
                          LPCCOMPLEXSCALAR    b   )
{
	*functionName = "rhoV_p@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO rhoV_p = 
{
    "rhoV_p",
    "a",
    "Saturated vapour density",
    (LPCFUNCTION)rhoV_pFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT rhoL_pFunction(   LPCOMPLEXSCALAR     a,
                          LPCCOMPLEXSCALAR    b   )
{
	*functionName = "rhoL_p@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO rhoL_p = 
{
    "rhoL_p",
    "a",
    "Saturated liquid density",
    (LPCFUNCTION)rhoL_pFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT rhoV_TFunction(   LPCOMPLEXSCALAR     a,
                          LPCCOMPLEXSCALAR    b   )
{
	*functionName = "rhoV_T@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO rhoV_T = 
{
    "rhoV_T",
    "a",
    "Saturated vapour density",
    (LPCFUNCTION)rhoV_TFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT rhoL_TFunction(   LPCOMPLEXSCALAR     a,
                          LPCCOMPLEXSCALAR    b   )
{
	*functionName = "rhoL_T@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO rhoL_T = 
{
    "rhoL_T",
    "a",
    "Saturated liquid density",
    (LPCFUNCTION)rhoL_TFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT rho_pTFunction(   LPCOMPLEXSCALAR     a,
                          LPCCOMPLEXSCALAR    b,  
					      LPCCOMPLEXSCALAR    c   )
{
	*functionName = "rho_pT@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO rho_pT = 
{
    "rho_pT",
    "a, b",
    "Density as a function of pressure and temperature.",
    (LPCFUNCTION)rho_pTFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT rho_phFunction(   LPCOMPLEXSCALAR     a,
                          LPCCOMPLEXSCALAR    b,  
					      LPCCOMPLEXSCALAR    c   )
{
	*functionName = "rho_ph@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO rho_ph = 
{
    "rho_ph",
    "a, b",
    "Density as a function of pressure and enthalpy",
    (LPCFUNCTION)rho_phFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT rho_psFunction(   LPCOMPLEXSCALAR     a,
                          LPCCOMPLEXSCALAR    b,  
					      LPCCOMPLEXSCALAR    c   )
{
	*functionName = "rho_ps@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO rho_ps = 
{
    "rho_ps",
    "a, b",
    "Density as a function of pressure and entropy.",
    (LPCFUNCTION)rho_psFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT sV_pFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b   )
{
	*functionName = "sV_p@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO sV_p = 
{
    "sV_p",
    "a",
    "Saturated vapour entropy",
    (LPCFUNCTION)sV_pFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT sL_pFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b   )
{
	*functionName = "sL_p@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO sL_p = 
{
    "sL_p",
    "a",
    "Saturated liquid entropy",
    (LPCFUNCTION)sL_pFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT sV_TFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b   )
{
	*functionName = "sV_T@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO sV_T = 
{
    "sV_T",
    "a",
    "Saturated vapour entropy",
    (LPCFUNCTION)sV_TFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT sL_TFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b   )
{
	*functionName = "sL_T@8";
	return callOneArgFunction(a, b);
}
FUNCTIONINFO sL_T = 
{
    "sL_T",
    "a",
    "Saturated liquid entropy",
    (LPCFUNCTION)sL_TFunction,
    COMPLEX_SCALAR,
    1,
    { COMPLEX_SCALAR }
};

LRESULT s_pTFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b,  
					    LPCCOMPLEXSCALAR    c   )
{
	*functionName = "s_pT@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO s_pT = 
{
    "s_pT",
    "a, b",
    "Specific entropy as a function of pressure and temperature (Returns saturated vapour entalpy if mixture.)",
    (LPCFUNCTION)s_pTFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};

LRESULT s_phFunction(   LPCOMPLEXSCALAR     a,
                        LPCCOMPLEXSCALAR    b,  
					    LPCCOMPLEXSCALAR    c   )
{
	*functionName = "s_ph@16";
	return callTwoArgFunction(a, b, c);
}
FUNCTIONINFO s_ph = 
{
    "s_ph",
    "a, b",
    "Specific entropy as a function of pressure and enthalpy",
    (LPCFUNCTION)s_phFunction,
    COMPLEX_SCALAR,
    2,
    { COMPLEX_SCALAR, COMPLEX_SCALAR }
};


BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved);

BOOL WINAPI DllEntryPoint (HANDLE 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;
		
		CreateUserFunction( hDLL, &Tsat_p );
		CreateUserFunction( hDLL, &T_ph );
		CreateUserFunction( hDLL, &T_ps );
		CreateUserFunction( hDLL, &T_hs );
		CreateUserFunction( hDLL, &psat_T );
		CreateUserFunction( hDLL, &p_hs );
		CreateUserFunction( hDLL, &p_hrho );
		CreateUserFunction( hDLL, &hV_p );
		CreateUserFunction( hDLL, &hL_p );
		CreateUserFunction( hDLL, &hV_T );
		CreateUserFunction( hDLL, &hL_T );
		CreateUserFunction( hDLL, &h_pT );
		CreateUserFunction( hDLL, &h_ps );
		CreateUserFunction( hDLL, &h_px );
		CreateUserFunction( hDLL, &h_Tx );
		CreateUserFunction( hDLL, &h_prho );
		CreateUserFunction( hDLL, &vV_p );
		CreateUserFunction( hDLL, &vL_p );
		CreateUserFunction( hDLL, &vV_T );
		CreateUserFunction( hDLL, &vL_T );
		CreateUserFunction( hDLL, &v_pT );
		CreateUserFunction( hDLL, &v_ph );
		CreateUserFunction( hDLL, &v_ps );
		CreateUserFunction( hDLL, &rhoV_p);
		CreateUserFunction( hDLL, &rhoL_p);
		CreateUserFunction( hDLL, &rhoV_T);
		CreateUserFunction( hDLL, &rhoL_T);
		CreateUserFunction( hDLL, &rho_pT);
		CreateUserFunction( hDLL, &rho_ph);
		CreateUserFunction( hDLL, &rho_ps);
		CreateUserFunction( hDLL, &sV_p );
		CreateUserFunction( hDLL, &sL_p );
		CreateUserFunction( hDLL, &sV_T );
		CreateUserFunction( hDLL, &sL_T);
		CreateUserFunction( hDLL, &s_pT);
		CreateUserFunction( hDLL, &s_ph);
      break;

    case DLL_THREAD_ATTACH:         // A new thread is being created in the current process.
    case DLL_THREAD_DETACH:        // A thread is exiting cleanly.
    case DLL_PROCESS_DETACH:      // The calling process is detaching the DLL from its address space.

      if (!_CRT_INIT(hDLL, dwReason, lpReserved)) 
        return FALSE;
      break;

  }
  return TRUE;
}

#ifdef _MANAGED
#pragma managed(pop)
#endif

