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
gnagelAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

LischkeCommented:
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
0
gnagelAuthor Commented:
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...
0
LischkeCommented:
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
0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

gnagelAuthor Commented:
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.
0
LischkeCommented:
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
0
gnagelAuthor Commented:
// 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

0
gnagelAuthor Commented:
// 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

0
gnagelAuthor Commented:
// 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

0
LischkeCommented:
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
0
gnagelAuthor Commented:
I'll do a bit of fiddleling this afternoon and see if I can anything, also get a demo program for you.

Thanks
Greg
0
LischkeCommented:
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
0
LischkeCommented:
After reading again what I wrote in my last comment, I realized that I haven't mentioned the most important fact (but I believe you saw it already in the provided solution).

Using "var" with a structure is the same (seen from the view of parameter passing) as using no modifier and passing a pointer to the structure. So if you write "out pdecOut: PDecimal" your are passing a pointer to a pointer to a structure.

Ciao, Mike
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
gnagelAuthor Commented:
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
0
LischkeCommented:
Glad to help you :-))

Ciao, Mike
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.