闲来无事想练习下用Python作为游戏脚本绑定到C++,网上搜了下,Python文档有些例子,但是太过复杂,gayhub无意中看到有人用Boost Python绑定,简单粗暴,省时省力,记录备忘。

写本文时使用

boost 1.69

python 3.71

首先在VS中配置好boost和python的include以及lib目录,自不必多说。

然后来个Hello World级别的例子,C++调用py脚本及定义的函数,py脚本调用C++定义的函数

先来C++部分

boost_python_hello.cpp

#include <iostream>

#include <boost/python.hpp>

using namespace std;

using namespace boost::python;

#if PY_MAJOR_VERSION >= 3
#   define INIT_MODULE PyInit_mymodule
extern "C" PyObject* INIT_MODULE();
#else
#   define INIT_MODULE initmymodule
extern "C" void INIT_MODULE();
#endif

char const* fun_from_cpp()
{
	return "fun_from_cpp";
}

int add_from_cpp(int a, int b)
{
	return (a+b);
}

int main(int argc, char** argv)
{
	try
	{
		Py_Initialize();

		object main_module = import("__main__");
		object main_namespace = main_module.attr("__dict__");

		main_namespace["fun_from_cpp"] = fun_from_cpp;
		main_namespace["add_from_cpp"] = add_from_cpp;

		object ignored1= exec_file("hello.py", main_namespace, main_namespace);

		object ignored2 = exec("show_py()", main_namespace);
		object ignored3 = exec("add_py_show(9, 8)", main_namespace);
		//object ignored4 = exec("result = 5 ** 2", main_namespace);

		int five_squared = extract<int>(main_namespace["result"]);

		cout << "result from main_namespace is : " << five_squared << endl;

	}
	catch (error_already_set& e)
	{
		PyErr_PrintEx(0);
		return 1;
	}

	return 0;
}

  

再来py脚本部分

hello.py

def show_py():
	print("fun from show_py function")

def add_py_show(a, b):
	print("fun from add_py_show function")
	print(a, "+", b, "=", a+b)

def add_py(a, b):
	return (a+b)

result = 2 * 3
result = add_py(1, 2)

print(fun_from_cpp())
print("add_from_cpp, 4 + 5 = ", add_from_cpp(4, 5))

  

显示结果

fun_from_cpp
add_from_cpp, 4 + 5 =  9
fun from show_py function
fun from add_py_show function
9 + 8 = 17
result from main_namespace is : 3

  

需要注意的是,运行时需要python目录在环境变量中,并且

boost_python37-vc141-mt-x32-1_69.dll

boost_python37-vc141-mt-gd-x32-1_69.dll

要放到运行的可执行文件目录下,以防找不到文件导致运行失败。

前者是Release下使用的,后者是Debug下使用的。

过程分析。

首先exec_file运行了hello.py脚本

object ignored1= exec_file("hello.py", main_namespace, main_namespace);

  

运行后,main_namespace的result 值为3,因为add_py(1, 2)返回值为3

result = add_py(1, 2)

  

然后,在py中调用了两个C++中定义的函数,fun_from_cpp和add_from_cpp

print(fun_from_cpp())
print("add_from_cpp, 4 + 5 = ", add_from_cpp(4, 5))

  

接下来C++又调用py中定义的函数

object ignored2 = exec("show_py()", main_namespace);
object ignored3 = exec("add_py_show(9, 8)", main_namespace);

  

最后提取py中result的值,并显示

int five_squared = extract<int>(main_namespace["result"]);
cout << "result from main_namespace is : " << five_squared << endl;

  

结果为3

如果把C++部分注释掉的代码解开

object ignored4 = exec("result = 5 ** 2", main_namespace);

  

将影响最终结果,5 * 5 = 25

更多例子可以参考boost python的文档

boost_1_69_0\libs\python\index.html

以及gayhub例子

https://github.com/TNG/boost-python-examples

========================================

今天试了下把程序放到虚似机中运行,测试依赖库,在没装python3.71的时候,直接运行显示缺少python37.dll

把dll复制过去依然不行,接着显示

Fatal Python error: initfsencoding: unable to load the file system codec ModuleNotFoundError: No module named 'encodings'

搜了一下,可以在C++程序中手动指定python目录的方法解决

Py_SetPythonHome(L"./Python37-32");
Py_Initialize();

  

这样就可以在无需安装python的情况下运行脚本了,但是目前还是不知道python安装器是怎么做到不用这句话就能正确找到py目录的,虽然安装器装完后在PATH环境变量中有python根目录和Scripts目录,

但是自己手动加入的话还是解决不了这个问题。

所以目前先用这个方法好了。

说起来python这个体积还是有点大,但是考虑到可以使用python的所有功能或许也值了?

7z单独打包python3.71是22.7 MB,解压后占用90 MB,参考了一下blender目录的python,似乎只要保留bin和lib目录就可以,测试发现的确如此,把py根目录的exe和lib目录留下,其他目录删掉也不影响运行。

当然现在只是简单的例子,只留exe和lib目录大根占用57.8 MB,和90 MB实在相差不多,所以精不精减意义不大。

考虑只用作PC运行,这个体积还算可以接受,最重要的是不用强制安装Python了,简化了一点操作。

Win7 VS2017 Boost Python入门的更多相关文章

  1. boost.python入门教程 ----python 嵌入c++

    Python语言简介 Python是一种脚本语言.以开放的开发接口和独特的语法著称.尽管Python在国内引起注意只有几年的时间,但实际上Python出现于上世纪90年代(据www.python.or ...

  2. 64位win7下安装Boost 1.59.0 + boost.python 1.59.0 + gccxml + pygccxml + pyplusplus(py++)

    由于安装过程中实在是出现了N多问题,所以不得不专门写个帖子来记录一下这破东西在Win7下的安装过程,避免以后还要再用的时候踩坑. 1.Boost简介 Boost库是一个可移植.提供源代码的C++库,作 ...

  3. python 入门教程

    转载自:http://www.crifan.com/files/doc/docbook/python_beginner_tutorial/release/html/python_beginner_tu ...

  4. [转]boost::python开发环境搭建

    转自:http://www.cnblogs.com/gaoxing/p/4317051.html 本来想用mingw编译boost::python模块,网上看了下资料太少,只有使用vs2012 操作环 ...

  5. boost::python开发环境搭建

    本来想用mingw编译boost::python模块,网上看了下资料太少,只有使用vs2012 操作环境:win7 x64 python: x86 boost: 1.57 编译boost::pytho ...

  6. win7+cuda+anaconda python+tensorflow-gpu+keras安装成功版本匹配汇总

    win7+cuda+anaconda python+tensorflow-gpu+keras安装成功版本匹配汇总 2019-09-20 15:06:03 wyx100 阅读数 38更多 分类专栏: M ...

  7. boost.python笔记

    boost.python笔记 标签: boost.python,python, C++ 简介 Boost.python是什么? 它是boost库的一部分,随boost一起安装,用来实现C++和Pyth ...

  8. Boost.Python简介

    Boost.Python简单概括:是Boost库的一部分:用来在C++代码中调用python代码以及在Python代码中调用C++代码,并且避免用户直接操作指针. 以下内容搬运自:https://wi ...

  9. python入门简介

    Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC ...

随机推荐

  1. makefile(一)

    Makefile的一个具体的实例 来源:http://blog.sina.com.cn/s/blog_73d4d5fa0100paiy.html (2011-03-06 23:10:02) 转载▼ 标 ...

  2. HTTP请求方式

    HTTP协议中请求的8中方法 OPTIONS获取服务器支持的HTTP请求方法: HEAD跟get很像,但是不返回响应体信息,用于检查对象是否存在,并获取包含在响应消息头中的信息. GET向特定的资源发 ...

  3. 判断序列B是否是序列A的连续子序列

    算法思想:因为两个整数序列已存入两个链表中,操作从两个链表的第一个结点开始,若对应得数据相等,则后移指针,若对应的数据不等,则A列表从上次开始比较结点的后继开始,B链表仍从第一个结点开始,直到B链表到 ...

  4. 求1!+2!+3!+......+n!的和 -----C++-----

    #include<iostream> using namespace std; int function(int x) { ; ;i<=x;i++) sum=sum*i; retur ...

  5. 使用Chrome浏览器访问谷歌和维基百科

    安装chrome插件 谷歌访问助手即可 就这么简单

  6. Linux下使用ps命令查看某个进程文件的启动位置

    ps -ef|grep shutdown ls -al /proc/4170

  7. python 编程

    1.一个str A,列表B的所有元素都在A中时返回True A = 'HeooWoldHomeUbuntuCentOSFedora'B = ['Ubuntu', 'CentOS', 'Home', ' ...

  8. Rust2018

    Rust已经有2本中文书了 <<深入浅出Rust>> <<Rust编程之道>> 带着aync的rust 2019会更精彩 看async , 在这里htt ...

  9. RabbitMQ 1

    RabbitMQ能做些什么? 消息系统允许软件.应用相互连接和扩展.这些应用可以相互链接起来组成一个更大的应用,或者将用户设备和数据进行连接.消息系统通过将消息的发送和接收分离来实现应用程序的异步和解 ...

  10. go语言环境安装

    Go 是一个开源的编程语言,被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言. 1. 准备环境并安装依赖包 创建centos 7.6 64bit的虚拟机. 安装 ...