We help IT Professionals succeed at work.

Parameter-Question ...

wimmeyvaert
wimmeyvaert asked
on
Hi Experts,

From my delphi-application, I do a call to a DLL-function.
This functions requires several parameters.
This is the function call :

procedure DsConR(var intRc: Smallint ; var DsId: TDistributionInfo ; var SecInfo: TSecurityInfo ;
                 var TimeOut: Longint ; SenderTag: PChar ; Expediter: PChar ; RecType: PChar ; Initiator: PChar); stdcall; external 'Vcomcl32.dll' name 'dsconr';

One of the parameters (SecInfo) is defined as (created new Type) :

Type
  TSecurityInfo = Record
    UsdLen : Word;
    UsData : PChar;
  end;


Now, from my application, I want to pass Nil as the 'SecInfo'-parameter when calling the function.
Is there a way to assign nil (nothing) to a user-defined Type ??
I hope someone can help me out here ...

Thanx in advance,
The Mayor.

PS : The application I'm writing uses VCOMCL32.DLL
     This is a C++ Library, developped by Volvo.
     Maybe one of you experts has also experience in
     developping delphi-applications with this VCOM-Lib.
     In this case any other information/help is welcome.
     You never know, do you.
Comment
Watch Question

Commented:
Hi,
im not one for this sort of thing but i remember you can do
something like this:

Type
 TSecurityInfo = Record
   UsdLen : Word;
   UsData : PChar;
 end;
PSecurityInfo = ^TSecurityInfo;

then use

procedure DsConR(var intRc: Smallint ; var DsId: TDistributionInfo ; var SecInfo: PSecurityInfo ;
                var TimeOut: Longint ; SenderTag: PChar ; Expediter: PChar ; RecType: PChar ; Initiator:
PChar); stdcall; external 'Vcomcl32.dll' name 'dsconr';

that should let you pass a nil to it.

hope it can help
Regards Barry

Commented:
Yes but without 'var'...
var <something> roughly means 'pointer to' <something> (parameter passed by reference).

SecInfo: PSecurityInfo (no var) can be used instead of var SecInfo: TSecurityInfo (at least from the Delphi client point of view):

procedure DsConR(var intRc: Smallint; var DsId: TDistributionInfo; SecInfo: PSecurityInfo; var TimeOut: Longint;
  SenderTag: PChar; Expediter: PChar; RecType: PChar; Initiator: PChar); stdcall;
  external 'Vcomcl32.dll' name 'dsconr';

Whether the DLL actually allows passing a nil pointer to this parameter is another question. Check your documentation.

Another note: C libraries sometimes use structure alignment options; if that's the case here then you may need to add 'packed' to the record declaration:

type
  PSecurityInfo = ^TSecurityInfo;
  TSecurityInfo = packed record
    UsdLen: Word;
    UsData: PChar;
  end;

Starting from Delphi 6, you can use the {$ALIGN} compiler directive to specify exact alignment to suit a particular C library.

Last note, because you're linking to the DLL statically (external 'Vcomcl32.dll'), your program will fail to run on a system where the DLL is not installed.

HTH
TOndrej

Commented:
Barry's solution is not compatible with the original API. It either has to be (1) "var SecInfo: TSecurityInfo" or (2) "SecInfo: PSecurityInfo". When using (1) you can't give in "nil", when using (2) you can. Using (2) is perfectly fine, if the API supports a nil there. All Windows APIs (see Windows.pas) are using (2) in that case.

Regards, Madshi.

Commented:
AAAHHH, TOndrej was faster...   :-)
hehe. having fun? :-)

Author

Commented:
Hi guys,

All you comments where in my mailbox this morning,
though you all replied on 10/19/2001.
I suppose there was something wrong on EE  ;-)

Anyway, I will check out all your suggestions today.

I'll be back ...

The Mayor.

Commented:
Hey, who is that guy?   :-)

Commented:
(Mean Vik, of course)

Author

Commented:
Hi Inthe, TOndrej,

First of all, Sorry for my late reply, but I had to work on another project last week.

I tried out your suggestions, but I get an AV when filling the PSecurity-Structure in my application.

This is my code-snippet to call the DSCONR-Function of the DLL :

    intRc               := 0;
    typDistrInfo.DsId   := '';
    { typSecurityInfo is declared as a unit-private variable and of type PSecurityInfo}
    typSecInfo.UsData   := ' ';  { Here I get my AV }
    typSecInfo.UsdLen   := Length(String(typSecInfo.UsData));
    lngTimeOut          := 0;
    strSender           := '';
    strExpediter        := 'NM11012Y';
    strRecType          := 'D';
    strInitiator        := '';
    DsConR(intRc, typDistrInfo, typSecInfo, lngTimeOut, strSender, strExpediter,strRecType, strInitiator);

Commented:
if you declare typSecInfo as PSecurityInfo it's not initialized by default and points to random memory address. That's why you get AV when accessing it.

First you have to allocate memory for the variable:

var
  PSecInfo: PSecurityInfo;
begin
  ...
  PSecInfo := AllocMem(SizeOf(TSecurityInfo));
  try
    ...
    DsConR(intRc, typDistrInfo, PSecInfo, lngTimeOut, strSender, strExpediter, strRecType, strInitiator);
  finally
    FreeMem(PSecInfo);
  end;
end;

You can use AllocMem (which initializes the allocated memory to zeros) or GetMem and explicitly initialize the record fields. Always make sure to call FreeMem to release the memory when you're done with it.

Or, you can make your life easier and let Delphi allocate/deallocate the memory automatically on the stack:
(You'll need to pass @SecInfo ie. address of your local variable which is in fact PSecInfo = pointer to TSecurityInfo.)

var
  SecInfo: TSecurityInfo;
begin
  ...
  SecInfo.UsData := '';
  SecInfo.UsdLen := 0;
  ...
  DsConR(intRc, typDistrInfo, @SecInfo, lngTimeOut, strSender, strExpediter, strRecType, strInitiator);
end;

HTH
TOndrej
wimmeyvaert:
This old question needs to be finalized -- accept an answer, split points, or get a refund.  For information on your options, please click here-> http:/help/closing.jsp#1 
EXPERTS:
Post your closing recommendations!  No comment means you don't care.

Explore More ContentExplore courses, solutions, and other research materials related to this topic.