Q:  Is there ANY way of calling a dll function at runtime if the DLL is not known about at compile time???

I am trying to call a DLL function at runtime.  I know the Name of the DLL, of the FUNCTION, and the PARAMETERS which need to be passed to it.  The only problem is that I do NOT know these items at the compile time of the App.  They will be retrieved from an INI file.

So far: I used LoadLibrary to get a handle to the DLL, I used GetProcAddress to get the address of the Function.  Now I have a TFarProc which is pointing to the function and I am STUCK!!!! :-(

A:

What you are trying to do is hard in a compiled language. I think you will have to drop to assembler for the actual function call.

I would go at it this way:

Do the LoadLibrary and GetProcAddress stuff as you do now, that is the easy part <g>. Then you need to evaluate the parameters and construct an image of the call stack frame in a buffer. That can be done in Pascal code without problem. Wrap the whole mess into a TStack object, for example, that has a Push method like

 Procedure TStack.Push( Var data; datasize: Word );

A quick sketch of such a beast would perhaps look like this:

Type
  TStack= Class
  private
    FPtr: Pointer;
    FSize: Word;
    FStackTop: Pointer;
    FUsed: Word;
    Function GetFree: Word;
  public
    Constructor Create( size: Word );
    Destructor Destroy; override;
    Procedure Push( Var data; datasize: Word );

    Property StackTop: Pointer read FStackTop;
    Property Free: Word read GetFree;
    Property Used: Word read FUsed
  end;

{  Methods of TStack  }
Function TStack.GetFree: Word;
  Begin
    Result := FSize - FUsed;
  End; { TStack.GetFree }

Constructor TStack.Create( size: Word );
  Begin
    inherited Create;
    FSize := size;
    GetMem( FPtr, size );
    FStackTop := FPtr;
    Inc( PtrRec( FStackTop ).ofs, size );
  End; { TStack.Create }

Destructor TStack.Destroy;
  Begin
    FreeMem( FPtr, size );
  End; { TStack.Destroy }

Procedure TStack.Push( Var data; datasize: Word );
  Begin
    If Free >= datasize Then Begin
      Dec( PtrRec( FStackTop ).ofs, datasize );
      Move( data, FStackTop^, datasize );
      Inc( FUsed, datasize );
    End { If }
    Else
      raise Exception.Create( 'Stack full!' );
  End; { TStack.Push }

So you create an instance of this animal and Push your parameters onto the stack. The actual call would then look something like this:

 Var
   Stack: TStack;
   size : Word;
   Top  : Pointer;
 Begin
   ..create stack and fill it
   size := Stack.Used;
   Top  := Stack.StackTop;
   asm
     mov cx, size
     jcxz @noParams
     mov ax, ss
     mov es, ax
     sub sp, cx
     mov di, sp
     push ds
     lds si, Top
     cld
     rep movsb
     pop ds
   @noParams:
     call DLLProc
     { add sp, size  only if DLLProc is cdecl and size <> 0! }
   end;
end;

One caveat: TStack.Push should raise an exception if you try to push data with an odd datasize; the CPU stack uses WORD as the smallest unit so only data with an even datasize can be pushed; odd size items like Char and Byte have to be extended to Words first!