-1

I want to access mpmath's special functions from a C code. I know how to do it via an intermediate python script. For instance, in order to evaluate the hypergeometric function, the C program:

#include <Python.h>

void main (int argc, char *argv[])
{
   int npars= 4;
   double a1, a2, b1, x, res;
   PyObject *pName, *pModule, *pFunc, *pArgs, *pValue;
   PyObject *pa1, *pa2, *pb1, *px;

   a1= atof(argv[1]);
   a2= atof(argv[2]);
   b1= atof(argv[3]);
   x= atof(argv[4]);

   setenv("PYTHONPATH", ".", 1); // Set PYTHONPATH TO bin directory
   Py_Initialize();

   pa1= PyFloat_FromDouble(a1);
   pa2= PyFloat_FromDouble(a2);
   pb1= PyFloat_FromDouble(b1);
   px=  PyFloat_FromDouble(x);
   pName = PyString_FromString("GGauss_2F1");
   pModule = PyImport_Import(pName);
   pFunc = PyObject_GetAttrString(pModule, "Gauss_2F1");
   pArgs = PyTuple_Pack(npars, pa1, pa2, pb1, px);
   pValue = PyObject_CallObject(pFunc, pArgs);

   res= PyFloat_AsDouble(pValue);
   printf("2F1(x)= %.15f\n", res);
}

works all right by calling the GGauss_2F1.py script:

from mpmath import *
def Gauss_2F1(a1, a2, b1, z):
   hpg= hyp2f1(a1, a2, b1, z)
   return hpg

Is there a way to call the mpmath function hyp2f1 directly from C, without having to resort to an intermediate python script? I guess that the mpmath module can be imported by the command

PyRun_SimpleString("from mpmath import *");   

But how do I access the actual function?

  • If you're writing a C program, why not use a C arbitrary-precision arithmetic library instead of a Python one? – user2357112 Sep 22 '16 at 18:04
  • Wait. The code you've written already imports a Python module, accesses a function defined in that module, packs arguments, and calls the function. That means you already know every tool you need to get your job done. Why didn't you just apply those tools to the `mpmath` module directly instead of writing a wrapper module? – user2357112 Sep 22 '16 at 18:07
  • _Why didn't you just apply those tools to the mpmath module directly instead of writing a wrapper module?_ – rgaelzer Sep 22 '16 at 19:57
  • _Why didn't you just apply those tools to the mpmath module directly instead of writing a wrapper module?_ Basically because I don't understand enough the C/Py API. AFAIU, `PyObject_GetAttrString(pModule, "Gauss_2F1")` will retrieve the function name (Gauss_2F1) from the python object GGauss_2F1. Then `PyObject_CallObject(pFunc, pArgs)` will evaluate the function with the parameters in the tuple pArgs. How do I evaluate directly hyp2f1 when pFunc must be a python object? – rgaelzer Sep 22 '16 at 20:08
  • Are you under the impression that `mpmath.hyp2f1` is *not* a Python object? You literally just do the exact same thing you did to access `GGauss_2F1.Gauss_2F1`, except with the names `mpmath` and `hyp2f1` instead of `GGauss_2F1` and `Gauss_2F1`. – user2357112 Sep 22 '16 at 20:11
  • Thanks for the tip. If I replace the lines from pName to pValue by: ` PyRun_SimpleString("from mpmath import *"); pArgs = PyTuple_Pack(npars, pa1, pa2, pb1, px); pFunc = PyString_FromString("mpmath.hyp2f1"); pValue = PyObject_CallObject(pFunc, pArgs);' the program compiles and executes, but the result is wrong. It seems that either the function mpmath.hyp2f1 is not actually called or the parameters aren't passed to it. – rgaelzer Sep 22 '16 at 20:29
  • What? No! Literally do the things you did to access `GGauss_2F1.Gauss_2F1`, just with the names changed. Why are you trying to `PyRun_SimpleString("from mpmath import *")`? – user2357112 Sep 22 '16 at 20:31

1 Answers1

0

What? No! Literally do the things you did to access GGauss_2F1.Gauss_2F1, just with the names changed. Why are you trying to PyRun_SimpleString("from mpmath import *")? – user2357112

Ok. Following your suggestions:

#include <Python.h>

void main (int argc, char *argv[])
{
   int npars= 4;
   double a1, a2, b1, x, res;
   PyObject *pName, *pModule, *pFunc, *pArgs, *pValue;
   PyObject *pa1, *pa2, *pb1, *px;

   a1= atof(argv[1]);
   a2= atof(argv[2]);
   b1= atof(argv[3]);
   x= atof(argv[4]);

   setenv("PYTHONPATH", ".", 1); // Set PYTHONPATH TO bin directory
   Py_Initialize();

   pa1= PyFloat_FromDouble(a1);
   pa2= PyFloat_FromDouble(a2);
   pb1= PyFloat_FromDouble(b1);
   px=  PyFloat_FromDouble(x);
   pName = PyString_FromString("mpmath");
   pModule = PyImport_Import(pName);
   pFunc = PyObject_GetAttrString(pModule, "hyp2f1");
   pArgs = PyTuple_Pack(npars, pa1, pa2, pb1, px);
   pValue = PyObject_CallObject(pFunc, pArgs);

   res= PyFloat_AsDouble(pValue);
   printf("2F1(x)= %.15f\n", res);
}

The code seems to work as expected and is generating the correct result. Thank you for your "patience"...