当前位置: 首页 > news >正文

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();
}

}

相关文章:

  • 字节外包凭借【ui自动化测试框架】成功进入内部编制
  • 用 Plop 加快项目相似代码生成
  • Codeforces Round #822 (Div. 2) 补题 (A、B、C)
  • 【初阶与进阶C++详解】第十六篇:AVL树-平衡搜索二叉树(定义+插入+旋转+验证)
  • 去除多重共线性的5种方法,你学废了嘛?
  • Verilog的奇技淫巧[更新中]
  • 被CTO推荐的SQL总结
  • 第八章 时序检查(下)
  • Android 10 低内存应用白名单和应用保活
  • 攻防演练中攻击队需要的安全技能第二篇
  • C#的File 类使用说明
  • 零基础能学大数据技术吗?学完能找到工作吗?
  • 实时即未来,车联网项目之远程诊断实时故障分析【七】
  • 《SpringBoot篇》10.JPQL超详细介绍与JPA命名规则
  • 【Android-实战】1、Room 使用 Flow 和 collect() 监听数据库的变化、动态更新页面
  • 【刷算法】求1+2+3+...+n
  • android 一些 utils
  • C# 免费离线人脸识别 2.0 Demo
  • es的写入过程
  • httpie使用详解
  • Linux后台研发超实用命令总结
  • MySQL几个简单SQL的优化
  • PAT A1050
  • sessionStorage和localStorage
  • 动态规划入门(以爬楼梯为例)
  • 分布式任务队列Celery
  • 服务器之间,相同帐号,实现免密钥登录
  • 高性能JavaScript阅读简记(三)
  • 给初学者:JavaScript 中数组操作注意点
  • 关于Flux,Vuex,Redux的思考
  • 记一次和乔布斯合作最难忘的经历
  • - 转 Ext2.0 form使用实例
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • ​ArcGIS Pro 如何批量删除字段
  • #android不同版本废弃api,新api。
  • #etcd#安装时出错
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (rabbitmq的高级特性)消息可靠性
  • (分布式缓存)Redis哨兵
  • (五)c52学习之旅-静态数码管
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (转)甲方乙方——赵民谈找工作
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .Net Core 中间件验签
  • .net 调用php,php 调用.net com组件 --
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .net6使用Sejil可视化日志
  • .net分布式压力测试工具(Beetle.DT)
  • .php结尾的域名,【php】php正则截取url中域名后的内容
  • :“Failed to access IIS metabase”解决方法
  • @test注解_Spring 自定义注解你了解过吗?
  • [28期] lamp兄弟连28期学员手册,请大家务必看一下
  • [4.9福建四校联考]