这章主要讲述在vc中如何调用Python程序
1、将程序的配置设为release
2、点击“项目”—“属性”—“配置属性”—“VC++目录”,在包含目录和库目录中将当前python程序下的include目录和libs目录的路径加进去。
3、头部添加
#include “python.h”
4、DecryptWork函数内部调用Python,具体步骤为
Py_Initialize(); //使用python之前,要调用Py_Initialize();这个函数进行初始化
if (!Py_IsInitialized() )
{
GetDlgItem(IDC_STATIC)->SetWindowTextW(_T("python初始化失败"));
return ;
}
PyObject * pModule = NULL; //文件名
PyObject * pFunc = NULL; //调用的函数
PyObject *pArgs = NULL; //传递的参数
PyObject *pReturn = NULL; //返回值
pModule =PyImport_ImportModule("decode"); //这里是要调用的Python文件名
if(!pModule)
{
GetDlgItem(IDC_STATIC)->SetWindowTextW(_T("python引入模块失败"));
return ;
}
pFunc= PyObject_GetAttrString(pModule, "urldecode"); //这里是要调用的函数名
if(!pFunc||!PyCallable_Check(pFunc))
{
GetDlgItem(IDC_STATIC)->SetWindowTextW(_T("python引入函数失败"));
return ;
}
//wchar*转为char*
int len= WideCharToMultiByte(CP_ACP,0,m_strinput,wcslen(m_strinput),NULL,0,NULL,NULL);
char *m_char=new char[len+1];
WideCharToMultiByte(CP_ACP,0,m_strinput,wcslen(m_strinput),m_char,len,NULL,NULL);
m_char[len]='\0';
pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", m_char));
pReturn = PyEval_CallObject(pFunc, pArgs); //调用函数,NULL表示参数为空
if(!pReturn)
{
GetDlgItem(IDC_STATIC)->SetWindowTextW(_T("python执行函数失败"));
return ;
}
//取返回值
char* cstr;
PyArg_Parse(pReturn, "s", &cstr);
//char*转为wchar*
int len1 = MultiByteToWideChar(CP_ACP,0,cstr,strlen(cstr),NULL,0);
wchar_t* m_wchar=new wchar_t[len1+1];
MultiByteToWideChar(CP_ACP,0,cstr,strlen(cstr),m_wchar,len1);
m_wchar[len1]='\0';
GetDlgItem(IDC_EDIT2)->SetWindowTextW(m_wchar);
//后续处理
delete m_char;
delete m_wchar;
Py_DECREF(pModule);
Py_DECREF(pFunc);
Py_DECREF(pArgs);
Py_DECREF(pReturn);
Py_Finalize(); //调用Py_Finalize,这个和Py_Initialize相对应的.
5、注意点
调用Python传递参数时,VC默认用的宽字节,需要先转为char*传入Python,否则好像会出错。
python返回给VC时,返回的是char*类型,需要先转为宽字节,然后输出。
另外需要注意的一点,调用Unicode加解密时,直接转会出现调用函数出错的情况,用了多种方式也不行,可能是因为char*传进去之后不允许再次进行unicode编码,确切的原因我也不知道。后来用了一种迂回的方式来解决。
新建一个StringToPy函数,用来将char*转为PyObject*类型,然后再传入python程序
PyObject* StringToPy(char* p_obj )
{
int len1 = MultiByteToWideChar(CP_ACP,0,p_obj,strlen(p_obj),NULL,0);
wchar_t* m_wchar=new wchar_t[len1+1];
MultiByteToWideChar(CP_ACP,0,p_obj,strlen(p_obj),m_wchar,len1);
m_wchar[len1]='\0';
PyObject* pb=PyUnicode_FromUnicode((const Py_UNICODE*)m_wchar,len1);
delete m_wchar;
return pb;
}
传递参数时改为
PyTuple_SetItem(pArgs, 0, Py_BuildValue("S", StringToPy(m_char)));
其他不需要改变,程序执行才不会出错。