python 代码 C 执行

12 篇文章 0 订阅

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

}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值