C与Python互调(加Boost/numpy/cvxopt的配置)

2 篇文章 0 订阅
1 篇文章 0 订阅


近期需要使用C语言调用Python的功能。
目前需求是想让C++代码中 像调用C自己的函数一样调用Python的..

下面总结下如何成功搭建环境并实现功能

本人使用的环境及软件版本为:
win10 vs2015 Python3.65 boost1.66 [numpy1.13.3 cvxopt1.2.0]


(本人已自己的环境搭建 所以下面的对应版本 大家可以依据自己的版本雷同修改
建议使用和本人一样的版本 因为可能会避免版本不统一无法正常编译的问题
win10 vs2015这两个基本环境 不在这里累赘讲了..)

 

首先需要下载Python

python官网下载地址:https://www.python.org/downloads/windows/
(本人使用的python-3.6.5-amd64.exe)
1.1 下载时 注意对应自己的 x64 x86 几点几python的版本
(刚刚认真接触python 2.X和3.X简直是两种语言..网上的大部分代码有的是2.X有的是3.X 且两种不能一起编译.. 感觉对新人不太友好..)

1.2 安装时 如忘记设置Python的Path 安装完毕之后 自行在环境变量中添加也可以
(添加 有python36.dll对应的路径即可)

安装完Python之后 可以在vs中尝试下是否可以正常使用 
配置Python环境如下
对应的头文件路径:

对应的库文件路径:

对应的依赖库名称:

(好像是不分debug 和 release)
配置好以上后随便找个代码测试:


// C代码: testPy.cpp
#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    Py_Initialize();

    // 将当前目录加入sys.path
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('./')");

    // 导入hello.py模块
    PyObject *pmodule = PyImport_ImportModule("hello");
    if (!pmodule)
    {
        printf("can't find pytest.py");
        return -1;
    }

    // 获得函数xprint对象,并调用,输出“hello world\n”
    PyObject *pfunc = PyObject_GetAttrString(pmodule, "xprint");
    PyObject_CallFunction(pfunc, NULL);

    // 获得类Hello并生成实例pinstance,并调用print成员函数,输出“5 6\n”
    PyObject *pclass = PyObject_GetAttrString(pmodule, "Hello");
    PyObject *arg = Py_BuildValue("(i)", 5);
    PyObject *pinstance = PyObject_Call(pclass, arg, NULL);
    PyObject_CallMethod(pinstance, "print", "i", 6);

    Py_DECREF(pmodule);
    Py_DECREF(pfunc);
    Py_DECREF(pclass);
    Py_DECREF(arg);
    Py_DECREF(pinstance);

    // 关闭Python
    Py_Finalize();
    return 0;
}

# python代码:hello.py
class Hello:
    def __init__(self, x):
        self.a = x
    def print(self, x=None):
        print(x)
def xprint():
    print("hello world")
 
if __name__ == "__main__":
    xprint()
    h = Hello(5)
    h.print()


此时可能会出现几个问题:

a.程序报错类似下面的错误
_caffe.obj : error LNK2019: unresolved external symbol __imp__Py_NegativeRefcount referenced in function _import_array
_caffe.obj : error LNK2019: unresolved external symbol __imp__Py_Dealloc referenced in function _import_array
_caffe.obj : error LNK2001: unresolved external symbol __imp__Py_RefTotal
 
  解决办法:找到python安装目录下的"pyconfig.h"文件, 进入修改
    #ifdef _DEBUG
    #   define Py_DEBUG
    #endif
  为
    #ifdef _DEBUG
    //# define Py_DEBUG
    #endif
  保存即可.

b.程序找不到"python36_d.lib"文件.
  解决方法:直接在Python安装目录下的libs目录中把对应的"python36.lib"额外拷贝出一个改名为"python36_d.lib".

c.程序无法找到"python36.dll".
  解决方法:可能是环境变量的路径设置问题,直接检查并添加正确的path.如果路径设置没问题,尝试把对应的"*.dll"文件拷贝到代码对应的路径下,执行程序.如果此时木有问题应该就是路径的问题产生,尝试重启电脑或者修改环境变量吧..也没准啥也没改 过两天它醒过闷儿来就不报错了..

上面的a b c问题结果完毕之后 程序可以正常执行并显示:
hello world
6

 

此时Python算安装完毕,下面安装boost库


boost官方下载地址:https://www.boost.org/
(本人使用的boost_1_66_0.zip)

下载好对应的版本开始配置
1.解压到你高兴的路径下.
2.在".\tools\build"下双击"bootstrap.bat"文件,稍后会生成"bjam.exe"和"b2.exe"文件.
(之前在另一台电脑上双击"bootstrap.bat"文件会失败,原因不明中..)
3.把"bjam.exe"文件拷贝到 刚刚解压的boost主目录中.
4.开始进入重要环节------生成lib
  在boost主目录中打开powershell 输入
  .\bjam --with-python --toolset=msvc-14.0 threading=multi link=shared address-model=64 runtime-link=shared variant=debug

  说明: 
--with-python 指boost下的python模块 安装完毕之后还需要换成
--with-thread; --with-date_time; --with-system; --with-chrono各执行一遍

--toolset=msvc-14.0 编译器版本

threading=multi 使用多线程(multi) 或者 单线程(single)

link=shared 使用静态库(static)还是共享库(shared)

runtime-link=shared 运行时链接C/C++标准库时 使用静态库(static)还是共享库(shared)

variant=debug 决定编译debug模式 还是release模式
(本人编译的debug版本release下也可以用..可能是boost::python不分debug/release..)

生成的*.lib和*.dll文件会生成在 boost主目录下的 "stage"目录下

生成所有所需的lib之后 配置boost的环境 
(include 和 lib的路径 在上面配置python的图片中)

这时开始执行可能会出现错误-----无法找到对应的*.lib 和 *.dll
解决办法同样是 把对应的*.lib改名成所需要的名称;把*.dll的path设置正确.

下面就可以执行简单的代码让C和Python牵手成功了..
// C代码 CP.cpp
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/python/call_method.hpp>
#include <vector>
#include <iostream>
#include <Python.h>
#include <string>
#include <boost/thread/thread.hpp>
boost::mutex io_mutex;
#include <boost/python/stl_iterator.hpp>

#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

#include <fstream>

using namespace std;
namespace bp = boost::python;

template<typename T>
void python_to_vector(bp::object o, vector<T> &v) {
    bp::stl_input_iterator<T> begin(o);
    bp::stl_input_iterator<T> end;
    v.clear();
    v.insert(v.end(), begin, end);
}

template<class T>
bp::list std_vector_to_py_list(const std::vector<T>& v)
{
    bp::object get_iter = bp::iterator<std::vector<T> >();
    bp::object iter = get_iter(v);
    bp::list l(iter);
    return l;
}

template <class T>
bp::list toPythonList(std::vector<T> vector) {
    typename std::vector<T>::iterator iter;
    bp::list list;
    for (iter = vector.begin(); iter != vector.end(); ++iter) {
        list.append(*iter);
    }
    return list;
}

bool readData(std::string _path, std::vector<double> &_vec, int _rows, int _cols) {
    std::ifstream infile(_path, std::ios::in);
    if (!infile.is_open()) {
        return false;
    }

    double temp;
    _vec.push_back(_rows);
    _vec.push_back(_cols);
    while (!infile.eof()) {
        infile >> temp;
        _vec.push_back(temp);
    }
    return true;
}

void newPython() {
    boost::mutex::scoped_lock
        lock(io_mutex);
    Py_Initialize();
    try
    {
        bp::object module;
        bp::object instance_ori;
        bp::object instance;

        vector<double> vec_ori_2DB;
        vec_ori_2DB.push_back(1.0);
        vec_ori_2DB.push_back(2.0);
//        readData("data_2DB.txt", vec_ori_2DB, 24, 76);

        vector<double> vec_ori_2DVd;
        vec_ori_2DVd.push_back(3.5);
        vec_ori_2DVd.push_back(5.5);
//        readData("data_2DVd.txt", vec_ori_2DVd, 24, 1);

        bp::list l_ori_Vd, l_ori_B;
        l_ori_Vd = toPythonList(vec_ori_2DB);
        l_ori_B = toPythonList(vec_ori_2DVd);
        //l_ori = std_vector_to_py_list(vec_ori); // error

        module = bp::import("Demo");

        instance = module.attr("myAdd")(l_ori_Vd, l_ori_B);

        bp::object obre = instance.attr("add")();

        vector<double> res;
        python_to_vector(obre, res);
        for (int i = 0; i< res.size(); i++)
            cout << res[i] << endl;

    }
    catch (...)
    {
        PyErr_Print();
        PyErr_Clear();
    }
}


int main()
{
    Py_Initialize();

    try
    {
        bp::object module = bp::import("sys");
        bp::object pythonpath = module.attr("path");
    }
    catch (...)
    {
        PyErr_Print();
        PyErr_Clear();
    }

    newPython();

    return 0;
}

// Demo.py
class myAdd():

  def __init__(self,data_Vd, data_B):
      self.data_Vd = data_Vd
      self.data_B = data_B
      self.result=[]

  def add(self): #__init__(self):
    for i in range(len(self.data_Vd )):
        x = self.data_Vd[i]+ self.data_B[i]
        self.result.append(x)
    return self.result 

(此时需要注意 需要把*.py文件放在对应的*.exe可执行文件下 才可以正常导入)
运行结果:
4.5
7.5


接下来开始讲解本人需要使用的Python下的cvxopt库和numpy的配置,如客官对这个兴趣不足速速离场即可.
希望上面的东西可以帮到你!

 

安装cvxopt其实只要下载对的*.whl 

cvxopt下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#cvxopt
(本人使用的cvxopt版本为cvxopt-1.2.0-cp36-cp36m-win_amd64.whl)

numpy也可以在上面的网址上下载
(本人使用的numpy-1.13.3+mkl-cp36-cp36m-win_amd64.whl版本)


下载完毕之后把上面2个文件拷贝到Python主目录中,并在Python主目录中打开Powershell之后依次执行以下 a b c 
a. .\python -m pip install numpy-1.13.3+mkl-cp36-cp36m-win_amd64.whl
b. .\python -m pip install -i https://pypi.douban.com/simple/ mkl
c. .\python -m pip install cvxopt-1.2.0-cp36-cp36m-win_amd64.whl

执行完以上3步之后点击python.exe
在输入 import numpy
和 import cvxopt 
显示如下

代表 耶! 万事大吉! 一切顺利!

End.. 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值