• python 代码 C 执行


    python C

    python 路径

    • 当我们导入一个模块时:import xxx ,默认情况下python解释器会搜索当前目录、已安装的内置模块和第三方模块。

    临时添加路径

    • sys.path 返回的是一个列表,该路径已经添加到系统的环境变量了

      • 当我们要添加自己的搜索目录时,可以通过列表的append()方法; sys.path.append()

      • 对于模块和自己写的脚本不在同一个目录下,在脚本开头加 sys.path.append('xxx')

    • 例如:

      • 导入的 xxx包在另一个项目文件中,在自己写的程序中需要用到该包时,首先加载导入的 xxx 包,加载的时候 python解释器会去 sys.path 默认搜索路径去搜索。

      • 如果通过 sys.path 中的路径可以搜索到 xxx包,然后加载。如果无法通过sys.path 中的路径搜索到xxx包,即说明自己的程序中引用的xxx包与自己程序脚本所在目录不在同一个路径。就需要将 xxx包的搜索路径添加到自己程序脚本的默认搜索路径中,重新运行自己的程序脚本。

    • 注意:

      • 这种方法是运行时修改,脚本运行后就会失效。

      • sys.path.append('..') 括号里这两个点是 上一级目录的意思,还可以 sys.path.append('../..')

    永久添加路径

    • 把路径添加到系统的环境变量,或把该路径的文件夹放进已经添加到系统环境变量的路径内。环境变量的内容会自动添加到模块搜索路径中。

    • 永久添加路径到sys.path中,方式有三

      • 将写好的py文件放到 已经添加到系统环境变量的 目录下

      • /usr/lib/python2.7/site-packages 下面新建一个.pth 文件(以pth作为后缀名) ,将模块的路径写进去,一行一个路径

      • 使用PYTHONPATH环境变量 export PYTHONPATH=$PYTHONPATH:/home/liu/shell/config

    append 导入案例:

    // 使用python之前,要调用Py_Initialize();这个函数进行初始化
    Py_Initialize();
    
    // 判断初始化是否成功
    if(!Py_IsInitialized()) {
        LOG(ERROR)<<"python init failed !";
        return ;
    }
    
    // 添加python文件所在的位置
    std::string python_path = std::string(common::kSourceDirectory) + "/hybrid_slam/tmp/";
    PyRun_SimpleString("import sys");  // 导入sys库
    std::string cmd_path = "sys.path.append(\"" + python_path + "\")";
    LOG(INFO)<<"path: "<<cmd_path;
    PyRun_SimpleString(cmd_path.c_str());  // 添加环境变换
    
    

    C 执行 python code 步骤

    • 第零步 初始化,并 导入python文件位置

      • 使用python之前,要调用Py_Initialize();这个函数进行初始化 Py_Initialize();
      • 添加python文件所在的环境,其实就是该python执行了 sys,path.append
    • 第一步是 导入.py文件:

      • 1.1、 使用 PyObject* pModule 来存储导入的 .py 文件模块, 调用的方法是 PyImport_ImportModule(path):
        Eg:PyObject* pModule = PyImport_ImportModule("test_py");
      • 1.2、 使用PyObject* pDict来存储导入模块中的方法字典, 调用的方法是 PyModule_GetDict(module):
        Eg: PyObject* pDict = PyModule_GetDict(pModule);
    • 第二步是导入已导入模块中的方法或类:

      • 2.1、 获取方法, 调用的方法是 PyDict_GetItemString(dict, methodName):
        Eg: PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi");

      • **2.2、**获取类,调用的方法同上, 注意后面的字符串对应于.py文件中的类/方法名:
        Eg: PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second");

      • 上面两步中获取字典可以不需要,直接基于名字得到对象 PyObject_GetAttrString(module, "TestPrint")

        Eg: pFunc = PyObject_GetAttrString(pModule, "TestPrint"); //这里是要调用的函数名

    • 第三步是使用导入的方法或类

      • **3.1、**使用方法, 调用PyObject_CallFunction(pFunc, "s", args)即可:
        PyObject_CallFunction(pFunHi, “s”, “lhb”);
      • **3.2、**使用类构造对象, 调用 PyInstance_New(pClass, NULL, NULL) 即可:
        PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL);
        • 注意,python3使用 PyObject *pConstruct = PyInstanceMethod_New(pClassPerson); ``//python3
        • 注意其中的pClassSecond为第二步.2中获取的类指针
      • **3.3、**使用类对象的方法, 调用PyObject_CallMethod(pInstance, methodname, "O", args)即可:
        Eg: PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson);
    • 第四步销毁这些对象: Py_DECREF(pointer);

    • 第五步关闭,与第一步打开对应 Py_Finalize();

    构建python 参数

      /* Py_BuildValue 它识别一组类似于 PyArg_ParseTuple() 识别的格式单元,但参数(是函数的输入,而不是输出)不能是指针,只是值。
       *               它返回一个新的 Python 对象,适合从 Python 调用的 C 函数返回。
         类型对应:
             s:string=char*,
             s#:string_sub,
             z:s,
             z#:s#,
             i:int,
             b:i,
             h:short int,
             l:long int,
             c:char,
             d:double,
             f:float,
             o:pyobject
         转换函数:
              Py_BuildValue("")                        None
              Py_BuildValue("i", 123)                  123
              Py_BuildValue("iii", 123, 456, 789)      (123, 456, 789)
              Py_BuildValue("s", "hello")              'hello'
              Py_BuildValue("ss", "hello", "world")    ('hello', 'world')
              Py_BuildValue("s#", "hello", 4)          'hell'
              Py_BuildValue("()")                      ()
              Py_BuildValue("(i)", 123)                (123,)
              Py_BuildValue("(ii)", 123, 456)          (123, 456)
              Py_BuildValue("(i,i)", 123, 456)         (123, 456)
              Py_BuildValue("[i,i]", 123, 456)         [123, 456]
              Py_BuildValue("{s:i,s:i}",
                            "abc", 123, "def", 456)    {'abc': 123, 'def': 456}
              Py_BuildValue("((ii)(ii)) (ii)",
                            1, 2, 3, 4, 5, 6)          (((1, 2), (3, 4)), (5, 6))
       */
    

    返回结果 object->c

      /**
          int ok;
          int i, j;
          long k, l;
          const char *s;
          int size;
          ok = PyArg_ParseTuple(args, "lls", &k, &l, &s);   // Two longs and a string
               // Possible Python call: f(1, 2, 'three')
    
          ok = PyArg_ParseTuple(args, "s", &s);   // A string
               // Possible Python call: f('whoops!')
    
          ok = PyArg_ParseTuple(args, "lls", &k, &l, &s);  //  Two longs and a string
               // Possible Python call: f(1, 2, 'three')
    
          ok = PyArg_ParseTuple(args, "(ii)s#", &i, &j, &s, &size);
               // A pair of ints and a string, whose size is also returned
               // Possible Python call: f((1, 2), 'three')
    
          {
            const char *file;
            const char *mode = "r";
            int bufsize = 0;
            ok = PyArg_ParseTuple(args, "s|si", &file, &mode, &bufsize);
                // A string, and optionally another string and an integer
                // Possible Python calls:
                //    f('spam')
                //    f('spam', 'w')
                //    f('spam', 'wb', 100000)
          }
          {
            int left, top, right, bottom, h, v;
            ok = PyArg_ParseTuple(args, "((ii)(ii))(ii)",
                     &left, &top, &right, &bottom, &h, &v);
              // A rectangle and a point
              // Possible Python call:
              //   f(((0, 0), (400, 300)), (10, 10))
          }
    
          {
              Py_complex c;
              ok = PyArg_ParseTuple(args, "D:myfunction", &c);
                // a complex, also providing a function name for errors
                // Possible Python call: myfunction(1+2j)
          }
       **/
    

    案例

    测试一个打印 和 一个相加,其中相加返回一个整数

      // 测试 HelloWorld
      pFunc = PyObject_GetAttrString(pModule, "TestPrint"); //这里是要调用的函数名
      PyEval_CallObject(pFunc, NULL);            //调用函数,NULL表示参数为空 
    
      // 测试 Add,传两个int型参数
      pFunc = PyObject_GetAttrString(pModule, "TestAdd"); //Add:Python文件中的函数名
      {
        //创建参数:
        PyObject *pArgs = PyTuple_New(2);                 //函数调用的参数传递均是以元组的形式打包的,2表示参数个数
        PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 5)); //0---序号  i表示创建int型变量
        PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 7)); //1---序号
        //返回值
        PyObject *pReturn = NULL;
        pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数
        if(pReturn) {
          //将返回值转换为int类型
          int result;
          if(PyArg_Parse(pReturn, "i", &result)) { //i表示转换成int型变量
            LOG(INFO)<<"5+7 = "<<result;
            ASSERT_EQ(result,12);
          } else {
            LOG(ERROR)<<"TestAdd return trans int error";
          }
        } else {
          LOG(ERROR)<<"TestAdd return nullptr";
        }
      }
    
    
    python 端:
        def prRed(skk): print("\033[91m {}\033[00m" .format(skk))
        def prBlue(skk): print("\033[94m {}\033[00m" .format(skk))
        def TestPrint() :
            prRed("hello world print_test!")
    
        def TestAdd(a,b) :
            return a+b
    
    

    测试 一个二维位姿取逆

      // 测试 2d 位姿取逆
      pFunc = PyObject_GetAttrString(pModule, "Pose2dInverse1"); //Add:Python文件中的函数名
      {
        PyObject *pArgs = PyTuple_New(3);
        PyTuple_SetItem(pArgs, 0, Py_BuildValue("d", 1.));
        PyTuple_SetItem(pArgs, 1, Py_BuildValue("d", 2.));
        PyTuple_SetItem(pArgs, 2, Py_BuildValue("d", 30./180*3.1415926));
        //返回值
        PyObject *pReturn = NULL;
        pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数
    
        if(pReturn) {
          LOG(INFO)<<"Pose2dInverse1 have result";
    
          //将返回值转换为int类型
          const char* result;
          if(PyArg_Parse(pReturn, "s", &result)) {
            std::string sss(result);
            LOG(INFO)<<"Pose2dInverse1 : "<<sss;
          } else {
            LOG(ERROR)<<"Pose2dInverse1 trans double3 error";
          }
    
        } else {
          LOG(ERROR)<<"Pose2dInverse1 return nullptr";
        }
      }
    
      // 测试 2d 位姿取逆
      pFunc = PyObject_GetAttrString(pModule, "Pose2dInverse"); //Add:Python文件中的函数名
      {
        PyObject *pArgs = PyTuple_New(3);
        PyTuple_SetItem(pArgs, 0, Py_BuildValue("d", 1.));
        PyTuple_SetItem(pArgs, 1, Py_BuildValue("d", 2.));
        PyTuple_SetItem(pArgs, 2, Py_BuildValue("d", 30./180*3.1415926));
        //返回值
        PyObject *pReturn = NULL;
        pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数
    
        if(pReturn) {
          //将返回值转换为int类型
          double result[3];
          if(PyArg_ParseTuple(pReturn, "ddd", &result[0],&result[1],&result[2])) {
            LOG(INFO)<<"0result: "<<result[0]<<" "<<result[1]<<" "<<result[2];
          } else {
    
            LOG(ERROR)<<"Pose2dInverse trans double3 error";
          }
    
        } else {
          LOG(ERROR)<<"Pose2dInverse return nullptr";
        }
    
      }
    
    
    python 代码:
    
        def Pose2dInverse(x,y,yaw) :
            """
                2d pose 取 返
                in: x y yaw ; out: x_inv y_inv yaw_inv
            """
            r_yaw = -yaw
            r_x = -(math.cos(-yaw)*x - math.sin(-yaw) * y)
            r_y = -(math.sin(-yaw)*x + math.cos(-yaw) * y)
            prBlue("input:%f,%f,%f" % (x,y,yaw))
            prRed("output:%f,%f,%f" % (r_x,r_y,r_yaw))
            return (r_x,r_y,r_yaw)
    
        def Pose2dInverse1(x,y,yaw) :
            r_yaw = -yaw
            r_x = -(math.cos(-yaw)*x - math.sin(-yaw) * y)
            r_y = -(math.sin(-yaw)*x + math.cos(-yaw) * y)
            result = "%f,%f,%f" % (r_x,r_y,r_yaw)
            prRed(result)
            return result
    

    测试类

     测试类
    //获取Person类
    PyObject *pClassPerson = PyObject_GetAttrString(pModule, "Person");
    //创建Person类的实例
    PyObject *pConstruct = PyInstance_New(pClassPerson, NULL, NULL); //python2
    // PyObject *pConstruct = PyInstanceMethod_New(pClassPerson); //python3
    PyObject *pInstancePerson = PyObject_CallObject(pConstruct, NULL);
    //调用方法
    PyObject_CallMethod(pInstancePerson, "greet", "s", "Hello Kitty"); //s表示传递的是字符串,值为"Hello Kitty"
    
    
    
    python 代码:
        class Person:
            class 
            def sayHi(self):
                print("Hi!")
            def greet(self,obj):
                print("greet:%s" % obj)
        class Second:
            def invoke(self,obj):
                 obj.sayHi()
        def sayhi(name):
            print 'hi',name;
    

    测试案例

    #include "gtest/gtest.h"
    #include "glog/logging.h"
    
    #include "Python.h"
    
    #include "../../common/config.h"
    
    namespace hybrid_slam {
    
    namespace  {
    
    void PythonTest(){
    
      // 使用python之前,要调用Py_Initialize();这个函数进行初始化
      Py_Initialize();
    
      // 判断初始化是否成功
      if(!Py_IsInitialized()) {
        LOG(ERROR)<<"python init failed !";
        return ;
      }
    
      // 添加python文件所在的位置
      std::string python_path = std::string(common::kSourceDirectory) + "/hybrid_slam/tmp/";
      PyRun_SimpleString("import sys");  // 导入sys库
      std::string cmd_path = "sys.path.append(\"" + python_path + "\")";
      LOG(INFO)<<"path: "<<cmd_path;
      PyRun_SimpleString(cmd_path.c_str());  // 添加环境变换
      PyObject *pModule = NULL;                   //声明变量
      PyObject *pFunc = NULL;                     //声明变量
      pModule = PyImport_ImportModule("test_c"); //这里是要调用的Python文件名
    
      if(!pModule) {
        LOG(ERROR)<<"can not open python file";
        return ;
      }
    
      // 测试 HelloWorld
      pFunc = PyObject_GetAttrString(pModule, "TestPrint"); //这里是要调用的函数名
      PyEval_CallObject(pFunc, NULL);            //调用函数,NULL表示参数为空
    
    
      // 测试 Add,传两个int型参数
      pFunc = PyObject_GetAttrString(pModule, "TestAdd"); //Add:Python文件中的函数名
      {
        //创建参数:
        PyObject *pArgs = PyTuple_New(2);                 //函数调用的参数传递均是以元组的形式打包的,2表示参数个数
        PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 5)); //0---序号  i表示创建int型变量
        PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 7)); //1---序号
        //返回值
        PyObject *pReturn = NULL;
        pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数
        if(pReturn) {
          //将返回值转换为int类型
          int result;
          if(PyArg_Parse(pReturn, "i", &result)) { //i表示转换成int型变量
            LOG(INFO)<<"5+7 = "<<result;
            ASSERT_EQ(result,12);
          } else {
            LOG(ERROR)<<"TestAdd return trans int error";
          }
        } else {
          LOG(ERROR)<<"TestAdd return nullptr";
        }
    
      }
    
    
      // 测试 2d 位姿取逆
      pFunc = PyObject_GetAttrString(pModule, "Pose2dInverse1"); //Add:Python文件中的函数名
      {
        PyObject *pArgs = PyTuple_New(3);
        PyTuple_SetItem(pArgs, 0, Py_BuildValue("d", 1.));
        PyTuple_SetItem(pArgs, 1, Py_BuildValue("d", 2.));
        PyTuple_SetItem(pArgs, 2, Py_BuildValue("d", 30./180*3.1415926));
        //返回值
        PyObject *pReturn = NULL;
        pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数
    
        if(pReturn) {
          LOG(INFO)<<"Pose2dInverse1 have result";
    
          //将返回值转换为int类型
          const char* result;
    
          if(PyArg_Parse(pReturn, "s", &result)) {
            std::string sss(result);
            LOG(INFO)<<"Pose2dInverse1 : "<<sss;
          } else {
            LOG(ERROR)<<"Pose2dInverse1 trans double3 error";
          }
    
        } else {
          LOG(ERROR)<<"Pose2dInverse1 return nullptr";
        }
      }
    
    
    
      // 测试 2d 位姿取逆
      pFunc = PyObject_GetAttrString(pModule, "Pose2dInverse"); //Add:Python文件中的函数名
      {
        PyObject *pArgs = PyTuple_New(3);
        PyTuple_SetItem(pArgs, 0, Py_BuildValue("d", 1.));
        PyTuple_SetItem(pArgs, 1, Py_BuildValue("d", 2.));
        PyTuple_SetItem(pArgs, 2, Py_BuildValue("d", 30./180*3.1415926));
        //返回值
        PyObject *pReturn = NULL;
        pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数
    
        if(pReturn) {
          //将返回值转换为int类型
          double result[3];
          if(PyArg_ParseTuple(pReturn, "ddd", &result[0],&result[1],&result[2])) {
            LOG(INFO)<<"0result: "<<result[0]<<" "<<result[1]<<" "<<result[2];
          } else {
    
            LOG(ERROR)<<"Pose2dInverse trans double3 error";
          }
    
        } else {
          LOG(ERROR)<<"Pose2dInverse return nullptr";
        }
      }
      Py_DECREF(pFunc);
    
    
    
    
    //  class Person:
    //      class
    //      def sayHi(self):
    //          print("Hi!")
    //      def greet(self,obj):
    //          print("greet:%s" % obj)
    //  class Second:
    //      def invoke(self,obj):
    //           obj.sayHi()
    //  def sayhi(name):
    //      print 'hi',name;
    
      PyObject* pDict = PyModule_GetDict(pModule);
      if (!pDict) {
          LOG(ERROR)<<"Cant find dictionary.";
      }
      PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi");
      PyObject_CallFunction(pFunHi, "s", "lyb");
      Py_DECREF(pFunHi);
    
      // 获取Second类
      PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second");
      if (!pClassSecond) {
          printf("Cant find second class./n");
          return ;
      }
      //获取Person类
      PyObject* pClassPerson = PyDict_GetItemString(pDict, "Person");
      if (!pClassPerson) {
          printf("Cant find person class./n");
          return ;
      }
      //构造Second的实例
      PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL);
      if (!pInstanceSecond) {
          printf("Cant create second instance./n");
          return ;
      }
      //构造Person的实例
      PyObject* pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL);
      if (!pInstancePerson) {
          printf("Cant find person instance./n");
          return ;
      }
    
      //把person实例传入second的invoke方法
      PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson);
    
      //获取Person类
      //创建Person类的实例
      PyObject *pConstruct = PyInstance_New(pClassPerson, NULL, NULL); //python2
      // PyObject *pConstruct = PyInstanceMethod_New(pClassPerson); //python3
      PyObject *pInstancePerson1 = PyObject_CallObject(pConstruct, NULL);
          // 使用元组 args 给出的参数调用可调用的Python对象 callable 。如果不需要参数,则 args 可以为 NULL 。
          // 成功时返回调用结果,或引发异常,失败时返回 NULL 。
          //   这等效于Python表达式:callable(*args)。
      //调用方法
      PyObject_CallMethod(pConstruct, "greet", "s", "Hello Kitty"); //s表示传递的是字符串,值为"Hello Kitty"
    
    
      Py_DECREF(pInstanceSecond);
      Py_DECREF(pInstancePerson);
      Py_DECREF(pClassSecond);
      Py_DECREF(pClassPerson);
    
    
      //调用Py_Finalize,这个和Py_Initialize相对应的.
      Py_Finalize();
    }
    }
    
    TEST(pythonTest, python_function_test){
    
      PythonTest();
    }
    
    }
    
  • 相关阅读:
    白领要预防肾结石的发生
    在PyTorch里面利用transformers的Trainer微调预训练大模型
    2022年双十一百亿补贴,2022年聚划算双11玩法解读
    第14章 MySQL事务日志【3.事务篇】【MySQL高级】
    vue开发网站--对文章详情页的接口内容进行处理
    Unity URP简单烘焙场景步骤
    消息队列MQ核心原理全面总结(11大必会原理)
    【word技巧】Word制作试卷,ABCD选项如何对齐?
    测试老鸟浅谈unittest和pytest的区别
    Tomcat启动时出现乱码的解决方式
  • 原文地址:https://blog.csdn.net/xiaoma_bk/article/details/127114572