CPython

本文介绍了C++如何通过Python C API与Python进行交互,涉及Python数据类型的转换,如整型、浮点型、布尔型、字符串的相互转换,并展示了如何调用Python函数及类方法。同时,示例还涵盖了内存管理、模块导入和对象构造与销毁。
摘要由CSDN通过智能技术生成
  1. 数据类型
#include <stdio.h>
#include <Python.h>
using namespace std;
PyObject* none_object(){
    Py_RETURN_NONE;   // 不需要自己return
}
int main() {

    // 初始化Python虚拟机
    Py_Initialize();
    // 判断Python虚拟机是否成功
    if (Py_IsInitialized() == 0){
        printf("fal to initialize Python\n");
        return -1;
    }

    printf("server start\n");
    //
    // 第一种方式
    PyObject *py_ival = Py_BuildValue("i", -5987);   // Python有符号整型
    PyObject *py_ival2 = PyLong_FromLong(-8979);
    int ival = PyLong_AsLong(py_ival);   // 把Python有字符整型转换成C的有字符整型
    int ival2 = PyLong_AsLong(py_ival2);   // 把Python有字符整型转换成C的有字符整型
    printf("ival = %d, ival2 = %d\n", ival, ival2);

    // 第二种方式
    PyObject *py_uval = Py_BuildValue("I", 465486);   // Python无符号整型
    PyObject *py_uval2 = PyLong_FromUnsignedLong(1654864);
    unsigned int uval = PyLong_AsUnsignedLong(py_uval);        // 把Python无字符整型转换成C的无字符整型
    unsigned int uval2 = PyLong_AsUnsignedLong(py_uval2);        // 把Python无字符整型转换成C的无字符整型
    printf("uval = %u, uval2 = %u\n", uval, uval2);

    /
    PyObject *py_lval = Py_BuildValue("L", 45648946484984);   // Python 长整型
    long long c_lval = PyLong_AsLongLong(py_lval);   // 转换成C的长整型
    printf("clval = %lld\n", c_lval);

    // 第二种方式
    PyObject *py_lval2 = PyLong_FromLongLong(234234623454525);   // PyLong_FromLongLong 使用方法定义一个Python长整型
    long long c_lval2 = PyLong_AsLongLong(py_lval2);   // 转换成C的长整型
    printf("clval2 = %lld\n", c_lval2);


    /
    // 第一种方式
    float fval = 632.045;
    PyObject *py_fval = Py_BuildValue("d", fval);   // Python 浮点类型
    float c_fval = PyFloat_AsDouble(py_fval);    // C的浮点类型
    printf("fval = %f\n", c_fval);

    // 第二种方式
    double  dval = 48941546.578;
    PyObject *py_dval = PyFloat_FromDouble(dval);   // Python 浮点类型
    double c_dval = PyFloat_AsDouble(py_dval);   // C的浮点类型
    printf("c_dval = %lf\n", c_dval);


    ///
    bool bval = true;   // false 反之
    PyObject *py_bval = Py_BuildValue("b", bval);   // Python 布尔类型
    int c_bval = PyInt_AsLong(py_bval);
    printf("c_bval = %d\n", c_bval);

    // 第二种方式
    bool bval2 = false;
    PyObject *py_bval2 = PyBool_FromLong(bval2);   // Python 布尔类型
    int c_bval2 = PyInt_AsLong(py_bval2);
    printf("c_bval2 = %d\n", c_bval2);


    /
    // 第一种方式
    const char *pstr = "this is a test";
    PyObject *py_str = Py_BuildValue("s", pstr);   // Python 字符串对象
    char *c_pstr = PyString_AsString(py_str);   // 转成C的字符指针
    printf("c_pstr = %s\n", c_pstr);

    // 第二种方式
    const char *pstr2 = "this is a test1";
    PyObject *py_str2 = PyString_FromString(pstr2);   // Python 字符串对象
    char *c_pstr2 = PyString_AsString(py_str2);   // 转成C的字符指针
    printf("c_pstr2 = %s\n", c_pstr2);

    // 创建一个二进制的字符串对象
    // 第一种方式
    const int mem_len = 1024;
    char *mem = new char[mem_len];
    PyObject *py_mem = Py_BuildValue("s#", mem, mem_len);  // 1. 数据的类型 2. 指向数据的指针 3. 数据的长度
    int c_data_len = PyString_Size(py_mem);
    printf("c_data_len = %d\n", c_data_len);

    // 第二种方式
    PyObject *py_mem2 = PyString_FromStringAndSize(mem, mem_len);
    int c_data_len2 = PyString_Size(py_mem2);
    printf("c_data_len2 = %d\n", c_data_len2);


    
    const char *p_ustr = "兰玉磊";
    PyObject *py_unicode = PyUnicode_FromString(p_ustr);  // 把C的字符串转成Python的unicode

    // 把unicode转成C的字符串
    PyObject *py_utf8 = PyUnicode_AsUTF8String(py_unicode);   // 把unicode转成utf-8
    const char *c_string = PyString_AsString(py_utf8);   // 把utf-8转成c的字符串
    printf("c_utf8 = %s\n", c_string);

    // 格式化unicode字符串
    // 创建一个unicode字符串
    PyObject *py_unicode_fmt = PyUnicode_FromFormat("%s%d%s", "我今年", 18, "岁");
    // 把unicode转C字符串
    PyObject *py_utf8_fmt = PyUnicode_AsUTF8String(py_unicode_fmt);
    const char *utf8_fmt = PyString_AsString(py_utf8_fmt);
    printf("utf8_fmt = %s\n", utf8_fmt);

    //
    PyObject *py_ret = none_object();
    // 退出Python虚拟机
    Py_Finalize();
    return 0;
}
server start
ival = -5987, ival2 = -8979
uval = 465486, uval2 = 1654864
clval = 45648946484984
clval2 = 234234623454525
fval = 632.044983
c_dval = 48941546.578000
c_bval = 1
c_bval2 = 0
c_pstr = this is a test
c_pstr2 = this is a test1
c_data_len = 1024
c_data_len2 = 1024
c_utf8 = 兰玉磊
utf8_fmt = 我今年18岁

g++ atest.cc python-config --cflags python-config --libs

  1. 引入类和类中函数
  • example.cpp
#include "c_python_utils.h"
#include <stdio.h>

int main(int argc, char const *argv[])
{

    init();
    char* rlt_char = py_call("hello", "power", "liupan", "()");
    finit();

    printf("%s\n", rlt_char);

    return 0;
}

  • c_python_utils.h
#ifndef _DTCORE_C_PYTHON_UTILS_H_
#define _DTCORE_C_PYTHON_UTILS_H_

#include <Python.h>
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif /* C++ */

/**
* 调用python类中的成员函数
* @param module python脚本名称,不含扩展
* @param class_name python类名称
* @param function python类成员函数
* @param format python类函数参数格式
* @return 返回字符串
*/
char* py_call( const char* module, const char* class_name, char* function, char* format, ... )
{
    PyObject* pName     = NULL;
    PyObject* pMod         = NULL;
    PyObject* pDict     = NULL;
    PyObject* pClass    = NULL;
    PyObject* pInstance = NULL;
    PyObject* pParam     = NULL;
    PyObject* pResult     = NULL;

    // 导入模块
    pName = PyString_FromString(module);
    pMod = PyImport_Import(pName);
    if( !pMod )
    {
        return "";
    }

    // 获取模块字典属性
    pDict = PyModule_GetDict(pMod);
    if ( !pDict )
    {
        return "";
    }

    // 通过字典获取模块中的类
    pClass = PyDict_GetItemString(pDict, class_name);
    if ( !pClass )
    {
        return "";
    }

    pInstance = PyInstance_New(pClass, NULL, NULL);
    if ( !pInstance )
    {
        return "";
    }

    pResult = PyObject_CallMethod(pInstance, function, format);
    
    char *rlt_ch = NULL;
    PyArg_Parse( pResult, "s", &rlt_ch );

    return rlt_ch;
}

/**
* 一些环境的初始化
* 
*/
void init()
{
    Py_Initialize();
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('./')");
}

/**
* 逆初始化
*/
void finit()
{
    Py_Finalize();
}

#ifdef __cplusplus
} /* extern "C" */
#endif /* C++ */

#endif  //_DTCORE_C_PYTHON_UTILS_H_
  • hello.py
class power():
    def liupan(self):
        return "hello world"
  1. 引用计数
  • example.cpp
#include <Python.h>

int main(int argc, char *argv[])
{
    PyObject *pName, *pModule, *pFunc;
    PyObject *pArgs, *pValue;
    int i;

    if (argc < 3) {
        fprintf(stderr, "Usage: call pythonfile funcname [args]\n");
        return 1;
    }

    Py_Initialize();
    pName = PyString_FromString(argv[1]);

    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != NULL) {
        pFunc = PyObject_GetAttrString(pModule, argv[2]);
        /* pFunc is a new reference */

        if (pFunc && PyCallable_Check(pFunc)) {
            pArgs = PyTuple_New(argc - 3);
            for (i = 0; i < argc - 3; ++i) {
                pValue = PyInt_FromLong(atoi(argv[i + 3]));
                if (!pValue) {
                    Py_DECREF(pArgs);
                    Py_DECREF(pModule);
                    fprintf(stderr, "Cannot convert argument\n");
                    return 1;
                }
                /* pValue reference stolen here: */
                PyTuple_SetItem(pArgs, i, pValue);
            }
            pValue = PyObject_CallObject(pFunc, pArgs);
            Py_DECREF(pArgs);
            if (pValue != NULL) {
                printf("Result of call: %ld\n", PyInt_AsLong(pValue));
                Py_DECREF(pValue);
            }
            else {
                Py_DECREF(pFunc);
                Py_DECREF(pModule);
                PyErr_Print();
                fprintf(stderr, "Call failed\n");
                return 1;
            }
        }
        else {

            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]);
        }

        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load \"%s\"\n", argv[1]);
        return 1;
    }
    Py_Finalize();     // Finish the Python Interpreter
    return 0;
}
  • mul.py
def mul(a,b):
    print "Will compute", a, "times", b
    c = 0
    for i in range(0, a):
        c = c + b
    return c

./demo mul mul 2 3
Will compute 2 times 3
Result of call: 6

  1. 构造对象与销毁
    main.cpp
#include <Python.h>
#include <iostream>
#include <string>

int main(void) {
    Py_Initialize(); // 启动虚拟机
    if (!Py_IsInitialized())
        return -1;
    // 导入模块
    PyObject* pModule = PyImport_ImportModule("testpy");
    if (!pModule) {
        printf("Cant open python file!/n");
        return -1;
    }
    // 模块的字典列表
    PyObject* pDict = PyModule_GetDict(pModule);
    if (!pDict) {
        printf("Cant find dictionary./n");
        return -1;
    }
    // 演示函数调用
    PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi");
    PyObject_CallFunction(pFunHi, "s", "lhb");
    Py_DECREF(pFunHi);
    // 演示构造一个Python对象,并调用Class的方法
    // 获取Second类
    PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second");
    if (!pClassSecond) {
        printf("Cant find second class./n");
        return -1;
    }
    //获取Person类
    PyObject* pClassPerson = PyDict_GetItemString(pDict, "Person");
    if (!pClassPerson) {
        printf("Cant find person class./n");
        return -1;
    }
    //构造Second的实例
    PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL);
    if (!pInstanceSecond) {
        printf("Cant create second instance./n");
        return -1;
    }
    //构造Person的实例
    PyObject* pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL);
    if (!pInstancePerson) {
        printf("Cant find person instance./n");
        return -1;
    }
    //把person实例传入second的invoke方法
    PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson);
    //释放
    Py_DECREF(pInstanceSecond);
    Py_DECREF(pInstancePerson);
    Py_DECREF(pClassSecond);
    Py_DECREF(pClassPerson);
    Py_DECREF(pModule);
    Py_Finalize(); // 关闭虚拟机
    return 0;
}

testpy.py

#!/usr/bin/python
class Person:
    def sayHi(self):
        print 'hi'
class Second:
    def invoke(self,obj):
         obj.sayHi()
def sayhi(name):
    print 'hi',name;

导出当前路径 export PYTHONPATH=xxxx:$PYTHONPATH
g++ main.cpp -o main -lpython2.7 -I/usr/include/python2.7

  1. numpy-C-api
  • example_logit.c
#include "Python.h"
#include "math.h"
#include "numpy/ndarraytypes.h"
#include "numpy/ufuncobject.h"
#include "numpy/npy_3kcompat.h"

static PyMethodDef LogitMethods[] = {
        {NULL, NULL, 0, NULL}
};

static void double_logit(char **args, npy_intp *dimensions,
                            npy_intp* steps, void* data)
{
    npy_intp i;
    npy_intp n = dimensions[0];
    char *in = args[0], *out = args[1];
    npy_intp in_step = steps[0], out_step = steps[1];

    double tmp;

    for (i = 0; i < n; i++) {
        /*BEGIN main ufunc computation*/
        tmp = *(double *)in;
        tmp /= 1-tmp;
        *((double *)out) = log(tmp);
        /*END main ufunc computation*/

        in += in_step;
        out += out_step;
    }
}

/*This a pointer to the above function*/
PyUFuncGenericFunction funcs[1] = {&double_logit};

/* These are the input and return dtypes of logit.*/
static char types[2] = {NPY_DOUBLE, NPY_DOUBLE};

static void *data[1] = {NULL};

#if PY_VERSION_HEX >= 0x03000000
static struct PyModuleDef moduledef = {
    PyModuleDef_HEAD_INIT,
    "npufunc",
    NULL,
    -1,
    LogitMethods,
    NULL,
    NULL,
    NULL,
    NULL
};

PyMODINIT_FUNC PyInit_npufunc(void)
{
    PyObject *m, *logit, *d;
    m = PyModule_Create(&moduledef);
    if (!m) {
        return NULL;
    }

    import_array();
    import_umath();

    logit = PyUFunc_FromFuncAndData(funcs, data, types, 1, 1, 1,
                                    PyUFunc_None, "logit",
                                    "logit_docstring", 0);

    d = PyModule_GetDict(m);

    PyDict_SetItemString(d, "logit", logit);
    Py_DECREF(logit);

    return m;
}
#else
PyMODINIT_FUNC initnpufunc(void)
{
    PyObject *m, *logit, *d;


    m = Py_InitModule("npufunc", LogitMethods);
    if (m == NULL) {
        return;
    }

    import_array();
    import_umath();

    logit = PyUFunc_FromFuncAndData(funcs, data, types, 1, 1, 1,
                                    PyUFunc_None, "logit",
                                    "logit_docstring", 0);

    d = PyModule_GetDict(m);

    PyDict_SetItemString(d, "logit", logit);
    Py_DECREF(logit);
}
#endif
  • setup.py
def configuration(parent_package='', top_path=None):
    import numpy
    from numpy.distutils.misc_util import Configuration

    config = Configuration('.',
                           parent_package,
                           top_path)
    config.add_extension('npufunc', ['example_logit.c'])

    return config

if __name__ == "__main__":
    from numpy.distutils.core import setup
    setup(configuration=configuration)
  • test.py
import numpy as np
import npufunc
npufunc.logit(0.5)
a = np.linspace(0,1,5)
print(a)
print(npufunc.logit(a))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值