Calling dll with an unknown # of parameters.

Windows specific forum
jassing
Addict
Addict
Posts: 1745
Joined: Wed Feb 17, 2010 12:00 am

Calling dll with an unknown # of parameters.

Post by jassing »

I have an app (syslog server) that does filtering & runs rules based on incoming data.
One of the requests I have is, instead of running a program, is to call a dll.
I have a few options:
1) make the requirement for the dll be a fixed function name & fixed variable / structure list.
2) do what the client wants (they're paying me)

Which is: they specify a dll and function, and what parameters to send. This can be a varying number of parameters. This precludes specifying a structure as a parameter -- but what I can't wrap my head around is how to call it.

my initial thought was to figure out the parameter count, and then just have a select paramCount and callFunction() set up with varying parameters.
BUT... this is a problem, parameters could be string, byte, word, long in any order....

I thought about using something like lua scripting and pass system variables to it & write out the parameter list.
Then I thought it might be easier to RunDLL32, but this requires specific dll format.

So, before I get vested in one of those -- anyone have any ideas?
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: Calling dll with an unknown # of parameters.

Post by RASHAD »

Hi
Search for "PBOSL GlobalSharedMemory"
Or
Share map bet Dll & application by idle
See which one suit you
Egypt my love
freak
PureBasic Team
PureBasic Team
Posts: 5929
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Calling dll with an unknown # of parameters.

Post by freak »

If you want to do full dynamic calls into an unknown dll you could use libFFI: https://sourceware.org/libffi/ Although this is probably some work to integrate into PB.

A simpler solution that could still work quite well especially if you can limit the max number of parameters and maybe even the allowed parameter types is simply to have a list of "dispatcher" procedures in your code for various parameter combinations. Then select the right one at runtime and call that.

Like this:

Code: Select all

; no parameters
Prototype Proto001()
Procedure Dispatch001(FunctionPointer.Proto001, Array Args.s(1))
  FunctionPointer()
EndProcedure

; one integer arg
Prototype Proto002(Arg1.i)
Procedure Dispatch002(FunctionPointer.Proto002, Array Args.s(1))
  FunctionPointer(Val(Args(0)))
EndProcedure

;...

; more complex combination
Prototype ProtoXXX(Arg1.i, Arg2.f, Arg3.s)
Procedure DispatchXXX(FunctionPointer.ProtoXXX, Array Args.s(1))
  FunctionPointer(Val(Args(0)), ValF(Args(1)), Args(2))
EndProcedure
Each PB procedure has the same arguments (function pointer and array of string parameters) so it can be called through a common prototype. It then does the actual call into the dll function with the properly converted parameters.

Then you can create a table that describes the dispatcher functions like this:

Code: Select all

DataSection
  DispatcherData:  
  ;      Function pointer  Parameter List                   End of entry
  Data.i @Dispatch001(),                                    -1
  Data.i @Dispatch002(),   #PB_Integer,                     -1
  
  ;...
  Data.i @DispatchXXX(),   #PB_Integer, #PB_Float, #PB_String, -1
  
  ; end of data
  Data.i 0
EndDataSection
The code to call the dll would then need to scan this table for the right parameter combination, get the dispatcher pointer and just call it with the real dll function and array of arguments as a string.

You could build this glue code by hand or write a small PB program to generate it for you. This will of course not allow all possible combinations of parameters, but you could generate enough such dispatcher functions so it is flexible enough for your customer.
quidquid Latine dictum sit altum videtur
jassing
Addict
Addict
Posts: 1745
Joined: Wed Feb 17, 2010 12:00 am

Re: Calling dll with an unknown # of parameters.

Post by jassing »

Thank you @Rashad, @idle.

#idle -- that was one of my ideas, but it seemed to become overwhelming.
I asked if I could just send addresses rather than values, then this becomes a lot more simple.
(ie: v=10 dllFunc( @v ) )
Then, it's just a matter of calling func based on # of parameters, rather than type too.

You both have given me ideas & I am reading them now. Thank you very much! I appreciate your time.

Cheers
-josh
User avatar
idle
Always Here
Always Here
Posts: 5040
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Calling dll with an unknown # of parameters.

Post by idle »

Not sure which post Rashad was meaning, I did answer a similar question recently but I can't remember the details.

If you get desperate this might work out.

Code: Select all

Structure PBAny 
  type.b
  StructureUnion 
    a.a
    b.b 
    c.c
    u.u
    w.w
    l.l
    i.i
    f.f
    q.q
    d.d 
    *ptr 
  EndStructureUnion
  s.s
EndStructure   

Structure PBAnyArray
  count.l
  any.PBAny[0]
EndStructure 

Procedure MyFunction(*Params.PBAnyArray)
 Protected a 
  
 For a = 0 To *Params\count -1    
  Select *Params\any[a]\type 
    Case #PB_Word 
      Debug *Params\any[a]\w 
      
    Case #PB_Quad 
      Debug *Params\any[a]\q 
      
    Case #PB_Double 
      Debug *Params\any[a]\d 
      
    Case #PB_String 
      Debug *Params\any[a]\s 

  EndSelect
  Next 
EndProcedure

Procedure FreePBAnyArray(*ar.PBAnyArray) 
  Protected a 
  For a = 0 To *ar\count-1 
    ClearStructure(*ar\any[a],PBAny) 
  Next 
 FreeMemory(*ar)
EndProcedure

Macro NewPBAny(ptr,size) 
 ptr = AllocateMemory(SizeOf(PBAnyArray)+(SizeOf(PBAny)*size))
 ptr\count = size  
EndMacro   

Define *params.PBAnyArray 

NewPBAny(*params,4) 

*params\any[0]\type = #PB_Word 
*params\any[0]\w = 12345 

*params\any[1]\type = #PB_Quad 
*params\any[1]\q =  123456789 

*params\any[2]\type = #PB_Double 
*params\any[2]\d =  2 * #PI 

*params\any[3]\type = #PB_String  
*params\any[3]\s = "PureBasic V5.51 Beta 1 x64"

MyFunction(*params)

FreePBAnyArray(*params)
Windows 11, Manjaro, Raspberry Pi OS
Image
jassing
Addict
Addict
Posts: 1745
Joined: Wed Feb 17, 2010 12:00 am

Re: Calling dll with an unknown # of parameters.

Post by jassing »

idle wrote:Not sure which post Rashad was meaning, I did answer a similar question recently but I can't remember the details.
Rashad was replying to another post... I knew what it was referencing.

If you get desperate this might work out.
I'm only in control of the calling program, not the receiver dll.
One of my initial suggestions was to pass an array of variables, much like your example, an array of structured elements, which include the type of variable.

I'm investing time/energy into dynamically creating a lua script & calling it. I think this will be the cleanest way & to the customer, will only appear as doing what they want.

Code: Select all

Structure PBAny 
  type.b
  StructureUnion 
    a.a
    b.b 
    c.c
    u.u
    w.w
    l.l
    i.i
    f.f
    q.q
    d.d 
    *ptr 
  EndStructureUnion
  s.s
EndStructure   

Structure PBAnyArray
  count.l
  any.PBAny[0]
EndStructure 

Procedure MyFunction(*Params.PBAnyArray)
 Protected a 
  
 For a = 0 To *Params\count -1    
  Select *Params\any[a]\type 
    Case #PB_Word 
      Debug *Params\any[a]\w 
      
    Case #PB_Quad 
      Debug *Params\any[a]\q 
      
    Case #PB_Double 
      Debug *Params\any[a]\d 
      
    Case #PB_String 
      Debug *Params\any[a]\s 

  EndSelect
  Next 
EndProcedure

Procedure FreePBAnyArray(*ar.PBAnyArray) 
  Protected a 
  For a = 0 To *ar\count-1 
    ClearStructure(*ar\any[a],PBAny) 
  Next 
 FreeMemory(*ar)
EndProcedure

Macro NewPBAny(ptr,size) 
 ptr = AllocateMemory(SizeOf(PBAnyArray)+(SizeOf(PBAny)*size))
 ptr\count = size  
EndMacro   

Define *params.PBAnyArray 

NewPBAny(*params,4) 

*params\any[0]\type = #PB_Word 
*params\any[0]\w = 12345 

*params\any[1]\type = #PB_Quad 
*params\any[1]\q =  123456789 

*params\any[2]\type = #PB_Double 
*params\any[2]\d =  2 * #PI 

*params\any[3]\type = #PB_String  
*params\any[3]\s = "PureBasic V5.51 Beta 1 x64"

MyFunction(*params)

FreePBAnyArray(*params)
[/quote]
jassing
Addict
Addict
Posts: 1745
Joined: Wed Feb 17, 2010 12:00 am

Re: Calling dll with an unknown # of parameters.

Post by jassing »

Well; That was fun...

I enjoyed adding lua scripting to my app; it was suprisingly easy. but one thing I overlooked; lua has no native way to call a standard dll function; only way is thru extensions (which aren't pre-compiled). I will have to go back and try to negotiate a working solution. Grr. Services me right -- I just assumed a modern scripting engine would support calling native shared objects / dll. (Oh, it does support calling dll's, but only dll's that are coded for lua; which, in my case, defeats the purpose, as I need to call existing standard dll functions)
Post Reply