主程序与python的双向交互

3 篇文章 0 订阅

        如果需要用脚本来扩展一个程序的功能,或是定制差异化的客制功能,或是用脚本自动运行一系列需要手动执行的操作, 可以考虑用python脚本来实现。当然也可以用lua脚本来实现,不过python库更丰富,可扩展空间更大。

        要达成上述功能,就需要主程序与python能够实现双向交互,即主程序可以调用python脚本并取得结果,python脚本也可以调用主程序的功能。

        已知主程序是可以单向调用python解释器来执行脚本的,也已知python可以通过ctypes库来调用Dll中的函数。当然主程序可以调用Dll更是众所周知。如果三者在运行时同处一个进程空间,那就完全可以通过Dll这个中间媒介来达到主程序和python的双向交互。经验证,该方法完全可行。下面说说具体的实现步骤:

 

生成动态链接库

1. 本文所用VS版本为VS 2015 ,进入:文件- >新建->项目,新建一个MFC Dll工程,这里只是演示,因此所有设定都采用默认设定。

2.添加供外部调用的函数,添加MyDll.h和MyDll.cpp到工程中,代码如下:
  MyDll.h文件代码:

#pragma once

#ifdef MYDLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

typedef void(__stdcall * _tx_function)();

#ifdef __cplusplus
extern "C" {
#endif

	DLL_API void __stdcall set_tx_function(_tx_function tx_func);
	DLL_API void __stdcall perform_tx();

	DLL_API void __stdcall set_value(int v);
	DLL_API int __stdcall get_value();
}


 MyDll.cpp文件代码:

#include "StdAfx.h"
#include "MyDll.h"

int tmp = 0;
_tx_function tx_fun = NULL;

DLL_API void __stdcall set_tx_function(_tx_function tx_func)
{
	tx_fun = tx_func;
}

DLL_API void __stdcall perform_tx()
{
	if (tx_fun != NULL)
		tx_fun();
}

DLL_API void __stdcall set_value(int v)
{
	tmp = v;
}

DLL_API int __stdcall get_value()
{
	return tmp;
}

至此,提供给python和主程序调用的Dll编写完毕。

代码说明
Dll中定义了4个函数,

  • 函数set_tx_function是提供给主程序调用的,主程序将一个函数地址传给Dll,Dll用tx_fun保存起来。
  • 函数perform_tx是提供给python调用的,用于执行保存在tx_fun里的函数,这样通过间接执行主程序中的函数,就达到了python控制主程序的目的。
  • 函数set_value和get_value,主程序和python都可以调用,是用来验证在主程序或python中设定一个值之后,另一方取出的值是否有变化。实际验证,当一方设定该值时,另一方取该值时是会有变化的。这样也说明可以用python来修改主程序中的状态。
     

生成脚本


python调用Dll的代码如下:

from ctypes import *
api = WinDLL("MFCLibrary1.dll")
print(api.get_value())
api.set_value(200)
api.perform_tx()


生成主程序

进入VS,通过文件- >新建->项目,新建一个MFC应用程序

1. 加入对Dll库和Python库的引用,其中C:\Python27是Python的安装目录,如下图:




2.编写一个函数,用于设定到Dll中供python间接调用,代码如下:

void __stdcall tx_funtion( )
{	
	TRACE(_T("tx_funtion\n"));
	AfxMessageBox(_T("tx_funtion\n"));
	//..编写要控制主程序的代码
}

3.在主程序中启动执行python脚本,代码如下:

	Py_Initialize();

	set_tx_function(tx_funtion);

	PyObject * pModule = PyImport_ImportModule("python_call_dll");//python_call_dll为python脚本文件名

	int v = get_value();

	TRACE(_T("v=%d\n"),v);

	Py_Finalize();

从代码执行结果来看,会弹出消息框,说明pyton成功调用主程序中的函数,在python脚本中设定的值,在主程序中通过get_value取出来也是与脚本的设定值一致的,说明主程序与python之间的交互成功。

同理,C#,QT程序与Python的交互也可以如法炮制。

注意:如果你用的Python2.7, 在Debug下编译主程序时,如果出现“无法打开文件“python27_d.lib”的提示,需要将文件c:\Python27\include\pyconfig.h中的pragma comment(lib,"python27_d.lib"),改为pragma comment(lib,"python27.lib")

例程代码下载

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值