从C程序中调用Python函数

时间:2022-02-03 16:04:01

I have an application in C and at some point I need to solve a non-linear optimization problem. Unfortunately AFAIK there are very limited resources to do that in C (please let me know otherwise). However it is quite simple to do it in Python, e.g. scipy.optimize.minimize.

我在C中有一个应用程序,在某些时候我需要解决非线性优化问题。不幸的是,AFAIK在C中的资源非常有限(请让我知道其他情况)。但是在Python中使用它很简单,例如scipy.optimize.minimize。

While I was trying to do that I encountered some of what it seems to be very frequent pitfalls, e.g. Python.h not found, module not loading, segmentation fault on function call, etc.

当我试图这样做时,我遇到了一些似乎非常频繁的陷阱,例如未找到Python.h,模块未加载,函数调用时出现分段错误等。

What is a quick and easy first-timer’s way to link the two programs?

什么是快速简便的第一计时器链接这两个程序的方式?

1 个解决方案

#1


7  

There are some things that you have to make sure are in place in order to make this work:

为了使这项工作,你必须确保有一些事情:

  1. Make sure you have Python installed (you may need the python-dev package).
  2. 确保安装了Python(您可能需要python-dev包)。
  3. Locate your Python.h file, e.g. by locate Python.h. One of the occurrences should be in a sub(sub)folder in the include folder, e.g. the path should be something like ../include/python2.7/Python.h.
  4. 找到你的Python.h文件,例如通过找到Python.h。其中一个出现应该在include文件夹的sub(sub)文件夹中,例如路径应该是../include/python2.7/Python.h。
  5. Insert #include “<path_to_Python.h>" in your C code in order to be able to use the Python API.
  6. 在C代码中插入#include“ ”以便能够使用Python API。
  7. Use any tutorial to call your Python function. I used this one and it did the trick. However there were a couple of small points missing:

    使用任何教程来调用Python函数。我用过这个,它就是诀窍。然而,有几个小点缺失:

    • Whenever you use any Py<Name> function, e.g. PyImport_Import(), always check the result to make sure there was no error, e.g.

      每当你使用任何Py 函数时,例如PyImport_Import(),总是检查结果以确保没有错误,例如

      // Load the module object
      pModule = PyImport_Import(pName);
      
      if (!pModule)
      {
          PyErr_Print();
          printf("ERROR in pModule\n");
          exit(1);
      }
      
    • Immediately after initializing the Python interpreter, i.e. after Py_Initialize();, you have to append the current path to sys.path in order to be able to load your module (assuming it is located in your current directory):

      在初始化Python解释器之后,即在Py_Initialize();之后,您必须将当前路径附加到sys.path以便能够加载模块(假设它位于当前目录中):

      PyObject *sys = PyImport_ImportModule("sys");
      PyObject *path = PyObject_GetAttrString(sys, "path");
      PyList_Append(path, PyString_FromString("."));
      
  8. Keep in mind that when you give the name of your Python file, it has to be without the extension .py.
  9. 请记住,当您提供Python文件的名称时,它必须没有扩展名.py。
  10. Lastly, you have to do the following during compiling/linking:
    • Remember the ../include/python2.7/Python.h file you used before? Include the include folder in the list of the header files directories with the -I option in the gcc options during compilation, e.g. -I /System/Library/Frameworks/Python.framework/Versions/2.7/include.
    • 还记得以前用过的../include/python2.7/Python.h文件吗?在编译期间在gcc选项中使用-I选项在头文件目录列表中包含include文件夹,例如-I /System/Library/Frameworks/Python.framework/Versions/2.7/include。
    • Also pass to the linker the folder with the required libraries. It should be inside the same folder where the include folder is located, e.g. -L /System/Library/Frameworks/Python.framework/Versions/2.7/lib, along with the -lpython2.7 option (of course adjusting it accordingly to your Python version).
    • 还将具有所需库的文件夹传递给链接器。它应该位于包含文件夹所在的同一文件夹中,例如-L /System/Library/Frameworks/Python.framework/Versions/2.7/lib,以及-lpython2.7选项(当然根据你的Python版本调整它)。
  11. 最后,在编译/链接期间必须执行以下操作:还记得之前使用的../include/python2.7/Python.h文件吗?在编译期间在gcc选项中使用-I选项在头文件目录列表中包含include文件夹,例如-I /System/Library/Frameworks/Python.framework/Versions/2.7/include。还将具有所需库的文件夹传递给链接器。它应该位于包含文件夹所在的同一文件夹中,例如-L /System/Library/Frameworks/Python.framework/Versions/2.7/lib,以及-lpython2.7选项(当然根据你的Python版本调整它)。

Now you must be able to successfully compile and execute your C program that calls in it your Python program.

现在,您必须能够成功编译和执行调用Python程序的C程序。

I hope this was helpful and good luck!

我希望这是有益的,祝你好运!

Sources:

资料来源:

#1


7  

There are some things that you have to make sure are in place in order to make this work:

为了使这项工作,你必须确保有一些事情:

  1. Make sure you have Python installed (you may need the python-dev package).
  2. 确保安装了Python(您可能需要python-dev包)。
  3. Locate your Python.h file, e.g. by locate Python.h. One of the occurrences should be in a sub(sub)folder in the include folder, e.g. the path should be something like ../include/python2.7/Python.h.
  4. 找到你的Python.h文件,例如通过找到Python.h。其中一个出现应该在include文件夹的sub(sub)文件夹中,例如路径应该是../include/python2.7/Python.h。
  5. Insert #include “<path_to_Python.h>" in your C code in order to be able to use the Python API.
  6. 在C代码中插入#include“ ”以便能够使用Python API。
  7. Use any tutorial to call your Python function. I used this one and it did the trick. However there were a couple of small points missing:

    使用任何教程来调用Python函数。我用过这个,它就是诀窍。然而,有几个小点缺失:

    • Whenever you use any Py<Name> function, e.g. PyImport_Import(), always check the result to make sure there was no error, e.g.

      每当你使用任何Py 函数时,例如PyImport_Import(),总是检查结果以确保没有错误,例如

      // Load the module object
      pModule = PyImport_Import(pName);
      
      if (!pModule)
      {
          PyErr_Print();
          printf("ERROR in pModule\n");
          exit(1);
      }
      
    • Immediately after initializing the Python interpreter, i.e. after Py_Initialize();, you have to append the current path to sys.path in order to be able to load your module (assuming it is located in your current directory):

      在初始化Python解释器之后,即在Py_Initialize();之后,您必须将当前路径附加到sys.path以便能够加载模块(假设它位于当前目录中):

      PyObject *sys = PyImport_ImportModule("sys");
      PyObject *path = PyObject_GetAttrString(sys, "path");
      PyList_Append(path, PyString_FromString("."));
      
  8. Keep in mind that when you give the name of your Python file, it has to be without the extension .py.
  9. 请记住,当您提供Python文件的名称时,它必须没有扩展名.py。
  10. Lastly, you have to do the following during compiling/linking:
    • Remember the ../include/python2.7/Python.h file you used before? Include the include folder in the list of the header files directories with the -I option in the gcc options during compilation, e.g. -I /System/Library/Frameworks/Python.framework/Versions/2.7/include.
    • 还记得以前用过的../include/python2.7/Python.h文件吗?在编译期间在gcc选项中使用-I选项在头文件目录列表中包含include文件夹,例如-I /System/Library/Frameworks/Python.framework/Versions/2.7/include。
    • Also pass to the linker the folder with the required libraries. It should be inside the same folder where the include folder is located, e.g. -L /System/Library/Frameworks/Python.framework/Versions/2.7/lib, along with the -lpython2.7 option (of course adjusting it accordingly to your Python version).
    • 还将具有所需库的文件夹传递给链接器。它应该位于包含文件夹所在的同一文件夹中,例如-L /System/Library/Frameworks/Python.framework/Versions/2.7/lib,以及-lpython2.7选项(当然根据你的Python版本调整它)。
  11. 最后,在编译/链接期间必须执行以下操作:还记得之前使用的../include/python2.7/Python.h文件吗?在编译期间在gcc选项中使用-I选项在头文件目录列表中包含include文件夹,例如-I /System/Library/Frameworks/Python.framework/Versions/2.7/include。还将具有所需库的文件夹传递给链接器。它应该位于包含文件夹所在的同一文件夹中,例如-L /System/Library/Frameworks/Python.framework/Versions/2.7/lib,以及-lpython2.7选项(当然根据你的Python版本调整它)。

Now you must be able to successfully compile and execute your C program that calls in it your Python program.

现在,您必须能够成功编译和执行调用Python程序的C程序。

I hope this was helpful and good luck!

我希望这是有益的,祝你好运!

Sources:

资料来源: