Jump to content
softtouch

mainmodule.<functionname> dynamically?

Recommended Posts

Lets say I have an array with the following 2 strings in it:

 

ClickElement_ByXPATH

ClickElement_ByCSSSelector

 

I have Python function with the same name, so I could call MainModule.ClickElement_ByXPATH or MainModule.ClickElement_ByCSSSelector, which works.

 

Is there any way to create the funcname in the call MainModule.<funcname> based on the strings in the stringlist?

For example, when I get the first item in the stringlist (ClickElement_ByXPATH), how could I create a call to MainModule.<here the element from the stringlist>, similar I can do with rtti and delphi functions, so it would call MainModule.ClickElement_ByXPATH? With other words, creating the call based on the text in a stringlist.

Share this post


Link to post

Are you wanting to call a Python function dynamically from Delphi code? Or call a Delphi function dynamically from Python code? Its not clear what you are looking for. Can you provide an example? 

Share this post


Link to post
1 hour ago, Remy Lebeau said:

Are you wanting to call a Python function dynamically from Delphi code? Or call a Delphi function dynamically from Python code? Its not clear what you are looking for. Can you provide an example? 

I want to call python functions. Their names are in a stringlist.

 

With other words, how could I call a python function when the function name is a string?

Example: var s:='ClickElement_ByXPATH';

How can I call the corresponding python function, which has exactly that name?

 

 

Share this post


Link to post
1 hour ago, softtouch said:

I want to call python functions. Their names are in a stringlist.

How are you calling Python functions from Delphi code to begin with?

Share this post


Link to post
Posted (edited)
6 minutes ago, Remy Lebeau said:

How are you calling Python functions from Delphi code to begin with?

Via MainModule.<pythonfunction name here> (TPythonModule of P4D)

 

If the python function ClickElement_ByXPATH exist, I call it like MainModule.ClickElement_ByXPATH();

Edited by softtouch

Share this post


Link to post
Posted (edited)
5 hours ago, softtouch said:

TPythonModule of P4D

THAT'S an important piece of information that was missing.

 

Python4Delphi's MainModule is a function that returns a custom Variant holding a reference to Python's __main__ object.  A custom class named TPythonVariantType derived from Delphi's TInvokeableVariantType is used to allow such Variants to access properties and methods of the Python objects they hold.

 

So, in your example, when you call MainModule.ClickElement_ByXPATH, the Delphi compiler emits code to pass the MainModule Variant to Python4Delphi's implementation of TPythonVariantType.DoProcedure() or TPythonVariantType.DoFunction() (depending on whether a return value is used or not) to invoke the "ClickElement_ByXPATH" function by name at runtime.

 

So, to do what you are asking for, you could invoke TPythonVariantType.DoProcedure() manually, eg (UNTESTED!):

uses
  ..., Variants, VarPyth;

var
  custType: TCustomVariantType;
  v: Variant;
begin
  // MainModule.ClickElement_ByXPATH();
  if FindCustomVariantType(VarPython, custType) then
  begin
    v := MainModule;
    custType.DoProcedure(TVarData(v), 'ClickElement_ByXPATH', nil);
  end;
end;

 

 

Edited by Remy Lebeau

Share this post


Link to post
Posted (edited)

@Remy Lebeau approach should work.  (not tested)

 

Alternatively you can use the more efficient:

var
  PyMainModule: PPyObject;

PyMainModule := GetPythonEngine.GetMainModule;
GetPythonEngine.PyObject_CallMethod (PyMainModule, PAnsiChar(AnsiString(method_name)), nil);

 

Edited by pyscripter

Share this post


Link to post
7 hours ago, pyscripter said:

@Remy Lebeau approach should work.  (not tested)

 

Alternatively you can use the more efficient:


var
  PyMainModule: PPyObject;

PyMainModule := GetPythonEngine.GetMainModule;
GetPythonEngine.PyObject_CallMethod (PyMainModule, PAnsiChar(AnsiString(method_name)), nil);

 

Thank you, but how can I provide parameter to the call when using this approach like result:=MainModule.ClickElement_ByXPATH(param1,param2,param3...)

Share this post


Link to post

I did, but I cant get it to work unfortunately. Anyway, thanks for your help.

Share this post


Link to post

Note that if you get the PyObject corresponding to the function by using for instance

var
  PyMainModule: PPyObject;
  PyFunc: PPyObject;

PyMainModule := GetPythonEngine.GetMainModule;
PyFunc := GetPythonEngine.PyObject_GetAttrString (PyMainModule, PAnsiChar(AnsiString(method_name)));
// When you finish with PyFunc you need to decrease the refcount

 

You can then call the function in a number of different ways including the relatively high level:

 

    function   EvalFunction(pyfunc:PPyObject; const args: array of const): Variant;
 

Share this post


Link to post
7 minutes ago, pyscripter said:

Note that if you get the PyObject corresponding to the function by using for instance


var
  PyMainModule: PPyObject;
  PyFunc: PPyObject;

PyMainModule := GetPythonEngine.GetMainModule;
PyFunc := GetPythonEngine.PyObject_GetAttrString (PyMainModule, PAnsiChar(AnsiString(method_name)));
// When you finish with PyFunc you need to decrease the refcount

 

You can then call the function in a number of different ways including the relatively high level:

 

    function   EvalFunction(pyfunc:PPyObject; const args: array of const): Variant;
 

Thank you! This is actually working just fine!

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×