Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delphi wrapper #892

Closed
bru32 opened this issue Dec 9, 2015 · 21 comments
Closed

Delphi wrapper #892

bru32 opened this issue Dec 9, 2015 · 21 comments

Comments

@bru32
Copy link
Contributor

bru32 commented Dec 9, 2015

The Delphi wrapper seems to have some errors (probably just out of date). I had to do a bit of trial and error and managed to get most parts working.
[I tried to attach all the code but it wouldn't accept then - how do I submit some code?].

{
Delphi Interface for CoolProp
Bruce Wernick, 9 December 2015
}

unit cpIntf;

interface

const
cpdll = 'CoolProp.dll';

type
CoolChar = AnsiChar;
PCoolChar = PAnsiChar;
CoolStr = AnsiString;
CoolVec = array[0..1023] of CoolChar;

function get_global_param_string(
param: PCoolChar;
var res: CoolVec): LongInt; stdcall;
external cpdll name '_get_global_param_string@12';

function get_fluid_param_string(
fluid: PCoolChar; param: PCoolChar;
var Output: CoolVec): Longint; stdcall;
external cpdll name '_get_fluid_param_string@12';

function PropsSI(spec: PCoolChar;
prop1: PCoolChar; val1: Double;
prop2: PCoolChar; val2: Double;
ref: CoolStr): Double; stdcall;
external cpdll name '_PropsSI@32';

function Props1SI(spec: PCoolChar;
ref: CoolStr): Double; stdcall;
external cpdll name '_Props1SI@8';

function HAPropsSI(spec: PCoolChar;
prop1: PCoolChar; val1: Double;
prop2: PCoolChar; val2: Double;
prop3: PCoolChar; val3: Double): Double; stdcall;
external cpdll name '_HAPropsSI@40';

implementation

begin
end.

When I started using it, I kept getting the odd error. So, I plotted a ph-chart and on every error, I draw a yellow blob.
The attached picture shows R22 but a similar pattern happens with all the other fluids.
coolprop_error01

@ibell
Copy link
Contributor

ibell commented Dec 10, 2015

Bruce,

a) For the Delphi code, best would be if you could figure out how to do a
pull request . @jowr can you help him with that? Or you could do a bit of
googling. Like this, the formatting is destroyed.

b) I don't think there is anything wrong with R22 -
http://www.coolprop.org/dev/fluid_properties/fluids/R22.html#consistency-plots
(from the development docs). Maybe it's something funny with your code?
What error message(s) do you get?

On Wed, Dec 9, 2015 at 11:04 AM, Bruce Wernick notifications@github.com
wrote:

The Delphi wrapper seems to have some errors (probably just out of date).
I had to do a bit of trial and error and managed to get most parts working.
[I tried to attach all the code but it wouldn't accept then - how do I
submit some code?].

{
Delphi Interface for CoolProp
Bruce Wernick, 9 December 2015
}

unit cpIntf;

interface

const
cpdll = 'CoolProp.dll';

type
CoolChar = AnsiChar;
PCoolChar = PAnsiChar;
CoolStr = AnsiString;
CoolVec = array[0..1023] of CoolChar;

function get_global_param_string(
param: PCoolChar;
var res: CoolVec): LongInt; stdcall;
external cpdll name '_get_global_param_string@12';

function get_fluid_param_string(
fluid: PCoolChar; param: PCoolChar;
var Output: CoolVec): Longint; stdcall;
external cpdll name '_get_fluid_param_string@12';

function PropsSI(spec: PCoolChar;
prop1: PCoolChar; val1: Double;
prop2: PCoolChar; val2: Double;
ref: CoolStr): Double; stdcall;
external cpdll name '_PropsSI@32';

function Props1SI(spec: PCoolChar;
ref: CoolStr): Double; stdcall;
external cpdll name '_Props1SI@8';

function HAPropsSI(spec: PCoolChar;
prop1: PCoolChar; val1: Double;
prop2: PCoolChar; val2: Double;
prop3: PCoolChar; val3: Double): Double; stdcall;
external cpdll name '_HAPropsSI@40';

implementation

begin
end.

When I started using it, I kept getting the odd error. So, I plotted a
ph-chart and on every error, I draw a yellow blob.
The attached picture shows R22 but a similar pattern happens with all the
other fluids.
[image: coolprop_error01]
https://cloud.githubusercontent.com/assets/8019833/11693717/23fefdd2-9eaf-11e5-92db-5f6520671041.png


Reply to this email directly or view it on GitHub
#892.

@bru32
Copy link
Contributor Author

bru32 commented Dec 10, 2015

OK, I will try the pull request.

It could be a bug in my code but it is strange that it works correctly over the entire range except for this little region of high pressure liquid.

Here, you can see the actual line that crashes:

procedure TMainForm.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
h, p, t: Double;
i, j: Integer;
begin
h := MolChart.P2X(X);
p := MolChart.P2Y(Y);
try
// CoolProp crashes here! (at high pressure liquid)
t := PropsSI('T', 'P', 1e6_p, 'H', 1e3_h, CoolStr(ref))-273.15;
except
t := -99;
// paint a yellow blob at the position of the error
for j := -1 to 1 do
for i := -1 to 1 do
PaintBox1.Canvas.Pixels[X+i,Y+j] := clYellow;
end;
StaticText1.Caption := format('h=%0.3f, p=%0.3f, t=%0.2f', [h,p,t]);
end;

@bru32 bru32 closed this as completed Dec 10, 2015
@bru32
Copy link
Contributor Author

bru32 commented Dec 10, 2015

Sorry, I clicked the wrong button!

@bru32 bru32 reopened this Dec 10, 2015
@bru32
Copy link
Contributor Author

bru32 commented Dec 10, 2015

OK, I have created a pull request and copied a single Delphi project with all associated source code. I have commented all places in the code where it crashes. Strange thing is that if I wrap the error in a try/except, it actually does what it is expected.

@ibell
Copy link
Contributor

ibell commented Dec 10, 2015

Are you passing the correct arguments to the functions? For instance, in
the CoolPropLib.h, you have :

EXPORT_CODE long CONVENTION get_global_param_string(const char *param, char
*Output, int n);

and I don't see where in your code you pass the length of the output buffer.

On Wed, Dec 9, 2015 at 11:34 PM, Bruce Wernick notifications@github.com
wrote:

OK, I have created a pull request and copied a single Delphi project with
all associated source code. I have commented all places in the code where
it crashes. Strange thing is that if I wrap the error in a try/except, it
actually does what it is expected.


Reply to this email directly or view it on GitHub
#892 (comment).

@bru32
Copy link
Contributor Author

bru32 commented Dec 10, 2015

Ja, I wondered about that. Initially I had an integer but then I saw your Lazarus example didn't have it so I took it out.

function get_global_param_string(param: PAnsichar; var Output: TArrayOfAnsiChar): Longint;  stdcall; external COOL_PROP name '_get_global_param_string@8';
function get_fluid_param_string(fluid: PAnsichar; param: PAnsichar; var Output: TArrayOfAnsiChar): Longint; stdcall; external COOL_PROP name '_get_fluid_param_string@12';

You are right, I should go back to the C source to make sure the interface is correct.
Cheers.

@bru32
Copy link
Contributor Author

bru32 commented Dec 10, 2015

OK, the integer resolved the problem with these calls

get_global_param_string('version', res, 1024);
get_global_param_string('gitrevision', rev, 1024);
get_global_param_string('FluidsList', dat, 1024);

But, it doesn't explain the inconsistency here:

t := PropsSI('T', 'P', 1e6*p, 'H', 1e3*h, CoolStr(ref));

It works without problem everywhere except for that one little region!

@bru32
Copy link
Contributor Author

bru32 commented Dec 11, 2015

Here is a single point demo that illustrates the crash in the dll.

I've kept it as simple as possible to avoid any confusion.
Firstly, using the DLL with Delphi.

program project6;
{$apptype console}

function PropsSI(spec: PAnsiChar;
                 prop1: PAnsiChar; val1: Double;
                 prop2: PAnsiChar; val2: Double;
                 ref: PAnsiChar): Double; stdcall;
                 external 'CoolProp.dll' name '_PropsSI@32';

var
  p, h, t: double;
begin
  h := 330;
  p := 4.3; // no problem
  t := PropsSI('T', 'P', 1e6*p, 'H', 1e3*h, 'R22');
  writeln(t);
  p := 4.4; // crash
  t := PropsSI('T', 'P', 1e6*p, 'H', 1e3*h, 'R22');
  writeln(t);
  readln;
end.

Now, the same point with Python.

import CoolProp
from CoolProp.CoolProp import PropsSI

h = 330
p = 4.3 # no problem
t = PropsSI('T', 'P', 1e6*p, 'H', 1e3*h, 'R22')
print t
p = 4.4 # the line crashes the dll but works with Python
t = PropsSI('T', 'P', 1e6*p, 'H', 1e3*h, 'R22')
print t

The Python code runs without problems.

The DLL crash is a runtime error 207.
Apparently, 8087 stack overflow. Possibly due to recursive calls.

@ibell
Copy link
Contributor

ibell commented Dec 11, 2015

Thanks for the example. I plan to dig into this in the near future and see
what is funny about the DLL.

On Fri, Dec 11, 2015 at 11:51 AM, Bruce Wernick notifications@github.com
wrote:

Here is a single point demo that illustrates the crash in the dll.

I've kept it as simple as possible to avoid any confusion.
Firstly, using the DLL with Delphi.

program project6;
{$apptype console}

function PropsSI(spec: PAnsiChar;
prop1: PAnsiChar; val1: Double;
prop2: PAnsiChar; val2: Double;
ref: PAnsiChar): Double; stdcall;
external 'CoolProp.dll' name '_PropsSI@32';

var
p, h, t: double;
begin
h := 330;
p := 4.3; // no problem
t := PropsSI('T', 'P', 1e6_p, 'H', 1e3_h, 'R22');
writeln(t);
p := 4.4; // crash
t := PropsSI('T', 'P', 1e6_p, 'H', 1e3_h, 'R22');
writeln(t);
readln;
end.

Now, the same point with Python.

import CoolProp
from CoolProp.CoolProp import PropsSI

h = 330
p = 4.3 # no problem
t = PropsSI('T', 'P', 1e6_p, 'H', 1e3_h, 'R22')
print t
p = 4.4 # the line crashes the dll but works with Python
t = PropsSI('T', 'P', 1e6_p, 'H', 1e3_h, 'R22')
print t

The Python code runs without problems.

The DLL crash is a runtime error 207.
Apparently, 8087 stack overflow. Possibly due to recursive calls.


Reply to this email directly or view it on GitHub
#892 (comment).

@bru32
Copy link
Contributor Author

bru32 commented Dec 11, 2015

Here is a good clue.

If I disable the fpu exceptions, the DLL works.

Set8087CW($133f); // Disable all fpu exceptions

So, the fault is very likely to be something like the 8087 stack overflow from recursive calls
.

@ibell
Copy link
Contributor

ibell commented Dec 11, 2015

Very interesting. I think we are close to figuring out what is going on.

On Fri, Dec 11, 2015 at 12:08 PM, Bruce Wernick notifications@github.com
wrote:

Here is a good clue.

If I disable the fpu exceptions, the DLL works.

Set8087CW($133f); // Disable all fpu exceptions

So, the fault is very likely to be something like the 8087 stack overflow
from recursive calls
.


Reply to this email directly or view it on GitHub
#892 (comment).

@ibell
Copy link
Contributor

ibell commented Dec 12, 2015

Calling DLL from C++ (VS2013 64-bit for both DLL and executable, with default flags from cmake) works just fine

#define COOLPROP_LIB
#include "CoolPropLib.h"
#include <iostream>

int main(){
    double ooo = PropsSI("T", "P", 1e6*4.3, "H", 330e3, "R22");
    double fff = PropsSI("T", "P", 1e6*4.4, "H", 330e3, "R22");
    std::cout << ooo << " " << fff;
}

@ibell
Copy link
Contributor

ibell commented Dec 12, 2015

I tried calling the DLL from python with the exact inputs that cause you failure. Also, no failure.

Where do you get your DLL from? Did you built it yourself? If so,how did you build it?

@ibell
Copy link
Contributor

ibell commented Dec 12, 2015

I can't debug what I can't cause to fail.

@jowr
Copy link
Member

jowr commented Dec 12, 2015

This becomes very interesting for me too. The problems described in #891 are also related to calling a DLL from Delphi and I thought I handled all the fpu-related issues, but obviously, I did not succeed.

@bru32
Copy link
Contributor Author

bru32 commented Dec 12, 2015

I understand that you can't find a solution when you can't actually repeat the same problem. I have had the same thing with my own software.

Just to make things a little more confusing, here I use Python to read the same DLL and it works!

'''
Use CoolProp Windows 32bit dll from Python
Bruce Wernick, 12 December 2015
'''

from ctypes import *

cp = windll.LoadLibrary('CoolProp.dll')

PropsSI = cp.PropsSI
PropsSI.restype = c_double
PropsSI.argtyprd = [c_char_p, c_char_p, c_double, c_char_p, c_double, c_char_p]

spec = create_string_buffer('T', 1)
name1 = create_string_buffer('P', 1)
name2 = create_string_buffer('H', 1)
ref = create_string_buffer('R22', 3)

p = c_double(4.4e6)
h = c_double(330.0e3)
t = PropsSI(spec, name1, p, name2, h, ref)
print t

So, this means that there is a problem when called by Delphi.
But, I declared the same parameters and the Delphi program does work generally except for a few points.

@bru32
Copy link
Contributor Author

bru32 commented Dec 12, 2015

I will persist with the Delphi problem, maybe I can help to identify the cause. We know that the Delphi code works when the fpu exception is disabled. Could it be my Delphi settings?

@bru32
Copy link
Contributor Author

bru32 commented Dec 12, 2015

I have found some links suggests that this is common problem with Delphi. Apparently, most compilers disable the fpu while the Delphi compiler specifically enables it.
http://www.virtualdub.org/blog/pivot/entry.php?id=53
http://digital.ni.com/public.nsf/allkb/E6A73825E57FCD9F862570DD005E594F
The vistualdub author references an article by Charlie Calvert (unfortunately it's broken). Pity because Charlie has a lot of inside knowledge of the Delphi compiler.
Anyway, I disable the fpu in my CoolProp initialization and the code works without a single exception on all refrigerants.
My conclusion: The problem is only exposed in Delphi because of the enabled fpu. As far as I am concerned, that closes this problem,

@jowr
Copy link
Member

jowr commented Dec 12, 2015

Should we add a note to the Delphi/Lazarus wrapper page? Could you write a brief paragraph in #893 ?

@ibell
Copy link
Contributor

ibell commented Dec 12, 2015

Yes, I am very happy to hear this problem is only in Delphi !!! I tried
playing with everything that I could in the DLL, and I could never
replicate this behavior when calling from C++ or python, so I am pleased it
is not a real problem.

On Sat, Dec 12, 2015 at 10:04 AM, Jorrit Wronski notifications@github.com
wrote:

Should we add a note to the Delphi/Lazarus wrapper page? Could you write a
brief paragraph in #893 #893 ?


Reply to this email directly or view it on GitHub
#892 (comment).

@bru32
Copy link
Contributor Author

bru32 commented Dec 13, 2015

I have updated my project4 demo. It uses the win32 shared dll with Delphi and is working well with all refrigerants. For fun, I added some features like a screenshot and a copy selected point to clipboard.
I did also add a description text file.
I'm not sure how to get this into the main source as suggested by https://github.com/jowr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants