Page 1 of 1

Calling dll with an unknown # of parameters.

Posted: Tue Nov 27, 2018 4:05 am
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?

Re: Calling dll with an unknown # of parameters.

Posted: Tue Nov 27, 2018 9:59 pm
by RASHAD
Hi
Search for "PBOSL GlobalSharedMemory"
Or
Share map bet Dll & application by idle
See which one suit you

Re: Calling dll with an unknown # of parameters.

Posted: Tue Nov 27, 2018 11:56 pm
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.

Re: Calling dll with an unknown # of parameters.

Posted: Wed Nov 28, 2018 4:59 am
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

Re: Calling dll with an unknown # of parameters.

Posted: Wed Nov 28, 2018 10:46 am
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)

Re: Calling dll with an unknown # of parameters.

Posted: Wed Nov 28, 2018 10:52 pm
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]

Re: Calling dll with an unknown # of parameters.

Posted: Thu Nov 29, 2018 11:07 am
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)