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?
Calling dll with an unknown # of parameters.
Re: Calling dll with an unknown # of parameters.
Hi
Search for "PBOSL GlobalSharedMemory"
Or
Share map bet Dll & application by idle
See which one suit you
Search for "PBOSL GlobalSharedMemory"
Or
Share map bet Dll & application by idle
See which one suit you
Egypt my love
Re: Calling dll with an unknown # of parameters.
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:
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:
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.
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
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
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
Re: Calling dll with an unknown # of parameters.
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
#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.
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.
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
Re: Calling dll with an unknown # of parameters.
Rashad was replying to another post... I knew what it was referencing.idle wrote:Not sure which post Rashad was meaning, I did answer a similar question recently but I can't remember the details.
I'm only in control of the calling program, not the receiver dll.
If you get desperate this might work out.
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)
Re: Calling dll with an unknown # of parameters.
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)
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)