3

I'm using the Python C API to call a method. At present I am using PyObject_CallMethodObjArgs to do this. This is a variadic function:

PyObject* PyObject_CallMethodObjArgs(PyObject *o, PyObject *name, ..., NULL)

This is absolutely fine when the number of arguments is known at compile time. However, I have a scenario where the number of arguments is not known until runtime, they are supplied as an array.

In essence my issue is precisely the same as in this question: How can I pass an array as parameters to a vararg function?

The accepted answer there tells me that there is no solution to my problem.

Is there are way around this hurdle. If I cannot solve the problem using PyObject_CallMethodObjArgs is there an alternative function in the Python C API that can meet my needs?

For instance, PyObject_Call accepts parameters as a Python sequence object. Is it possible to use this function, or one with a similar interface?

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Please provide some [MCVE]. Your question is unclear. In what programming language are you coding in? – Basile Starynkevitch Feb 02 '18 at 14:02
  • 1
    I don't think that the programming language is relevant. After all, this is an API and therefore available to pretty much any programming language. – David Heffernan Feb 02 '18 at 14:05
  • Each programming language *implementation* has its own [calling convention](https://en.wikipedia.org/wiki/Calling_convention) so what programming language *implementation* you are using is *extremely* relevant. [SBCL](http://sbcl.org/) has not the same one as C (that is GCC on my Linux, which follows the Linux ABI) – Basile Starynkevitch Feb 02 '18 at 14:07
  • @BasileStarynkevitch I don't agree. I am looking for functions in the Python C API that avoid the need for varidiac argument passing. They exist for other function call like operations. I can call any function in the Python C API. – David Heffernan Feb 02 '18 at 14:09
  • Your question is then unclear. I voted to close it. – Basile Starynkevitch Feb 02 '18 at 14:09
  • If you vote to close then, which is your right, I guess you will delete your answer also. After all, closing says that you feel a question can't or shouldn't be answered. – David Heffernan Feb 02 '18 at 14:10
  • No, I often answer to unclear questions, ask the OP to improve them, and improve my answer accordingly to his improvements. I claim that the programming languages (& implementations, or ABIs) of both the calling function and the called function are extremely relevant. The fact that you code in Delphi is *very* important and should be mentioned in your question – Basile Starynkevitch Feb 02 '18 at 14:11
  • So, assuming that I can call all functions of the Python C API (I can), which ones should I use? I'm looking for expertise in the Python C API. I would like to know which functions in the Python C API to get around this hurdle, if there are indeed any. You appreciate that APIs are language neutral? – David Heffernan Feb 02 '18 at 14:13
  • You can use any function documented in [Embedding and extending Python](https://docs.python.org/3/extending/index.html) if you are coding in C some call (usage) of Python functions or coding in Python some call to C functions. But that chapter don't mention Delphi (and for good reasons). – Basile Starynkevitch Feb 02 '18 at 14:14
  • Right, so which ones do I use for this problem? – David Heffernan Feb 02 '18 at 14:15
  • I dont understand your actual problem. Smells a lot like some [XY problem](http://xyproblem.info). Please provide some [MCVE] – Basile Starynkevitch Feb 02 '18 at 14:15
  • 2
    No, I don't think you do understand my problem. – David Heffernan Feb 02 '18 at 14:16
  • Then provide some [MCVE] or show some *concrete* code with the actual call – Basile Starynkevitch Feb 02 '18 at 14:17
  • 2
    The problem is at your end. Don't worry about it. – David Heffernan Feb 02 '18 at 14:18

2 Answers2

5

I am not sure if I am completey wrong, but AFAICT it should be possible to

glglgl
  • 89,107
  • 13
  • 149
  • 217
  • What do I pass as the `callable_object` parameter? I suppose I'm wondering how to get `self` into the method. – David Heffernan Feb 02 '18 at 14:17
  • 1
    OK, I see, I can just use `PyObject_GetAttrString` passing the object ref and the method name, and it's all good. I guess what comes back from that is bound. So the answer was in my question after all! – David Heffernan Feb 02 '18 at 14:21
0

A possible way might be to use libffi, perhaps thru the ctypes Python library. It knows your ABI and calling conventions (so is partly coded in assembler, for many popular implementations) and enables you to call an arbitrary function of arbitrary signature and arbitrary arity.

Notice that there is no purely standard way of doing that (without using some external library à la libffi...) in portable and standard C11 (check by reading n1570).

BTW, libffi can be used from any C program. And ctypes can be used from any Python program.

The Python Embedding and extending Python chapter explains how to call Python from C, or C from Python.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547