Search code examples
cdelphipointersdlldelphi-xe7

Pointers passed by reference in Delphi (import functions from DLL)


I want to use a function declared in a DLL which takes pointers as in/out parameters to fill up a record with non-pointer parameters.

Function from DLL:

function WFS_GetMlaData(   handle: WFS_HDL;
                           mla_idx: Integer;
                           mla_name:  TCharWFSBufferArray;
                       var cam_pitch_um: PDouble;
                       var lenslet_pitch_um: PDouble;
                       var center_spot_offset_x: PDouble;
                       var center_spot_offset_y: PDouble;
                       var lenslet_f_um: PDouble;
                       var grd_corr_0: PDouble;
                       var grd_corr_45: PDouble): Integer stdcall;

Record:

MlaInfo = record
    i : Integer;
    idx : Integer;
    name : TCharWFSBufferArray;
    camPitchUm : double;
    lensletPitchUm : double;
    spotOffsetx : double;
    spotOffsety : double;
    lensletFocalLengthUm : double;
    grdCorr0 : double;
    grdCorr45 : double;
end;

Function call:

if err = WFS_GetMlaData(handle,
                        MlaList[i].idx,
                        MlaList[i].name,
                        PDouble(MlaList[i].camPitchUm),
                        PDouble(MlaList[i].lensletPitchUm),
                        PDouble(MlaList[i].spotOffsetx),
                        PDouble(MlaList[i].spotOffsety),
                        PDouble(MlaList[i].lensletFocalLengthUm),
                        PDouble(MlaList[i].grdCorr0),
                        PDouble(MlaList[i].grdCorr45) ) then MyWFS_HandleErrors(handle, err);

With a similar function which passes pointers to integer it works, in the case above I have Invalid Typecast error.


Solution

  • The answer is in the Parameters (Delphi) - Value and Variable Parameters documentation. My bold emphasizes it:

    If a routine's declaration specifies a var parameter, you must pass an assignable expression - that is, a variable, typed constant (in the {$J+} state), dereferenced pointer, field, or indexed variable to the routine when you call it.


    Regarding your case, my advice is to declare a new type:

    PMlaInfo = ^TMlaInfo;
    

    And change the signature of the function:

    function WFS_GetMlaData(AHandle: WFS_HDL; const AMlaInfo: PMlaInfo): Integer stdcall;
    

    But there's a sort of "hack" (dereferenced pointer):

    PDouble((@MlaList[i].camPitchUm)^)