Link to home
Start Free TrialLog in
Avatar of gnagel
gnagel

asked on

DECIMALs & Delphi

Hi

Quickly put: I need to use the VarDecFromStr function in oleaut32.dll (Actually I need to use all of the VarDec* functions) and Delphi
doesn't know about it.

Now the long version:

I'm having a few problems using Decimals in Delphi 4 (SP 3). I've got a COM
object written in C++ (MS) that passes a decimal inside a variant.

I eventually figured out how to get the decimal out on the Delphi side but
now I'm trying to create a decimal myself. I'm trying to use VarDecFromStr,
but Delphi 4 (and 5) does not have a header for this function. It's got headers for just about every other variant function in the OLE API but just about nothing related to decimals and variants.

So I went through the source files and found the declaration for VarBstrFromDec (the exact opposite of what I want, although I do use this
one also). So I copied that and changed it to VarDecFromStr (I made the right changes). Amazingly this actually worked.. well sort of. I've debuged
my code (at ASM level) and I definately know that VarDecFromStr is being
called. But as soon as my function (the one that makes the call to VarDecFromStr) exits I get an access violation. I've debugged this also and
it seems that when my function exists it pops the registers off the stack
(as one would expect), but something seems to go a bit wrong and the
execution point ends up at 0x00000000.. obviously a really bad thing.

So... has anyone ever used this before?? Or does anyone know of a header
file that has a delphi conversion of this routine?? Or has anyone got any
ideas??

Thanks
Greg
Avatar of Lischke
Lischke

Mmmh, this sounds very like a wrong calling convention. How's the declaration on the Delphi side? Does it contain the stdcall directive?

Ciao, Mike
Avatar of gnagel

ASKER

Yup, it's stdcall, I tried all 5 of them, safecall, cdecl, register, etc... no luck. Maybe there's a reason Delphi doesn't have headers for any of the VarDecFrom* functions...
Yes, this could be true. I'm not sure for what you need those functions and I'm also not sure if you can use them this way at all, as they use datatypes which may not be compatible with Delphi (e.g. what is DECIMAL?).

And even MSDN is very silent about those functions (VarDecFromStr is only mentioned two times, without nearer explanation or an example).

Ciao, Mike
Avatar of gnagel

ASKER

Well Delphi does at least know about a decimal, it's got the definitions for it.

My problem is that I'm using an SDK that we've written and some of the data members are decimals. I've managed to get the decimals out of it, but at the moment I've got no way to put/update it. That's why I need the VarDecFrom* functions, that way I can at least put something back into it.

We've got testers in VB and they handle it fine, ASP doesn't have a problem... at least not yet, and of course C++ works fine. It's just Delphi...

Oh, VarBstrFromDec uses the same parameter types as VarDecFromStr (just in a different order) and it works fine, in Delphi.
Ah yes, I see there's TDecimal in ActiveX.pas (but no entry in the help file :-/). I'd say your problem has nothing to do with datatypes as you are using the same in both mentioned functions. So it seems there's something different wrong. Read this statement form MSDN:

Remarks
Passing into this function any invalid and, under some circumstances, NULL pointers will result in unexpected termination of the application.
--- end of quote

Strange enough VarDecFromStr is not declared (even in D5), so you must have declared them yourself. Please post the declaration here. Another point I wonder about is that WideStrings are used as parameters, not PWideChars. This is very uncommon!

Ciao, Mike
Avatar of gnagel

ASKER

// HEre's Delphi's VarBStrFromDec
//function VarBStrFromDec(pdecIn: PDecimal; lcid: TLCID; dwFlags: Longint; out bstrOut: WideString): HResult; stdcall;

// Here's my VarDecFromStr
{$EXTERNALSYM VarDecFromStr}
function VarDecFromStr(bstrIn: WideString; lcid: TLCID; dwFlags: Longint; out pdecOut: PDecimal): HResult; stdcall;


// Here's the C++ declaration
{
HRESULT VarDecFromStr(
  OLECHAR*  strln,
  LCID  lcid,
  unsigned long  dwFlags,
  DECIMAL *  pdecOut
);
}

const
   oleaut32 = 'oleaut32.dll';

// Here's my VarDecFromStr
function VarDecFromStr; external oleaut32 name 'VarDecFromStr';

// Here's Delphi's VarBstrFromDec
function VarBstrFromDec;                external oleaut32 name 'VarBstrFromDec';

I didn't pick up that MSDN quote, I'll check it out and see if I'm passing through some invalid stuff.

Greg

Avatar of gnagel

ASKER

// HEre's Delphi's VarBStrFromDec
//function VarBStrFromDec(pdecIn: PDecimal; lcid: TLCID; dwFlags: Longint; out bstrOut: WideString): HResult; stdcall;

// Here's my VarDecFromStr
{$EXTERNALSYM VarDecFromStr}
function VarDecFromStr(bstrIn: WideString; lcid: TLCID; dwFlags: Longint; out pdecOut: PDecimal): HResult; stdcall;


// Here's the C++ declaration
{
HRESULT VarDecFromStr(
  OLECHAR*  strln,
  LCID  lcid,
  unsigned long  dwFlags,
  DECIMAL *  pdecOut
);
}

const
   oleaut32 = 'oleaut32.dll';

// Here's my VarDecFromStr
function VarDecFromStr; external oleaut32 name 'VarDecFromStr';

// Here's Delphi's VarBstrFromDec
function VarBstrFromDec;                external oleaut32 name 'VarBstrFromDec';

I didn't pick up that MSDN quote, I'll check it out and see if I'm passing through some invalid stuff.

Greg

Avatar of gnagel

ASKER

// HEre's Delphi's VarBStrFromDec
//function VarBStrFromDec(pdecIn: PDecimal; lcid: TLCID; dwFlags: Longint; out bstrOut: WideString): HResult; stdcall;

// Here's my VarDecFromStr
{$EXTERNALSYM VarDecFromStr}
function VarDecFromStr(bstrIn: WideString; lcid: TLCID; dwFlags: Longint; out pdecOut: PDecimal): HResult; stdcall;


// Here's the C++ declaration
{
HRESULT VarDecFromStr(
  OLECHAR*  strln,
  LCID  lcid,
  unsigned long  dwFlags,
  DECIMAL *  pdecOut
);
}

const
   oleaut32 = 'oleaut32.dll';

// Here's my VarDecFromStr
function VarDecFromStr; external oleaut32 name 'VarDecFromStr';

// Here's Delphi's VarBstrFromDec
function VarBstrFromDec;                external oleaut32 name 'VarBstrFromDec';

I didn't pick up that MSDN quote, I'll check it out and see if I'm passing through some invalid stuff.

Greg

Mmmh, seems all fine. I ran now out of ideas. Have you tried to vary the VarDecFromStr declaration? E.g. take out the "out" keyword or use "out pdecOut: TDecimal". If you can make a small demo program then send it to me and I debug it here (public@lischke-online.de).

Ciao, Mike
Avatar of gnagel

ASKER

I'll do a bit of fiddleling this afternoon and see if I can anything, also get a demo program for you.

Thanks
Greg
Hi Greg, I think I found it. After fiddling with calling conventions againa and a bit low level debugging I found out the stack is overwritten partially when calling VarDecFromStr. After thinking another while I came to the conclusion that the out keyword is wrong in the function declaration (as is the safecall convention). Better said: it isn't wrong but you need to consider that it is to your parameter as would you set "var" instead of "out". You can actually use "out", but it is used for interfaces not for normal structures. Anyway, pick one of both correct solutions:

function VarDecFromStr(bstrIn: WideString; lcid: TLCID; dwFlags: Longint; var pdecOut: TDecimal): HResult; stdcall;

function VarDecFromStr(bstrIn: WideString; lcid: TLCID; dwFlags: Longint; out pdecOut: TDecimal): HResult; stdcall;

Ciao, Mike
ASKER CERTIFIED SOLUTION
Avatar of Lischke
Lischke

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of gnagel

ASKER

IT WORKED!!

The final code is:
function VarDecFromStr(bstrIn: WideString; lcid: TLCID; dwFlags: Longint; out pdecOut: TDecimal): HResult; stdcall;

Var
   apDecimal : PDecimal;
begin
   VariantInit(Data);  // Initialize variant
   apDecimal := PDecimal(@Data);
   VarDecFromStr(aString, LOCALE_SYSTEM_DEFAULT, 0, apDecimal^);

Changing the out param to TDecimal fixed everything.

Thanks alot for the assistance Mike, I really appreciate it.

Greg
Glad to help you :-))

Ciao, Mike