1.python调用c++:
1.1 第一种调用方式:直接调用C++编译生成的exe文件
Python代码:
import os
cpptest = r".\cpp.exe" # exe路径,linux中不加后缀exe
os.system(cpptest + ' ' + path) # 中文使用GBK编码
C++代码:
void main(int argc, char* argv[])
{
//输出传进来的参数及个数
cout << "argc:"<< argc << endl;
cout << "argv:"<< argv[0] << endl;
return;
}
调用非常简单,但是要注意以下问题:
a. os.system(cpptest + ' ' + path)
这句话就是调用cpptest路径中的exe文件并传参,这里我传递的是一个含有中文的路径path,实测要将python的File Encoding改为GBK或者GB2312,按理说使用默认的UTF-8是可以传递中文的,这里没太搞懂;
b. 括号中的每一项都要用空格(' '
)分开,再用加号连接;
c. 这种传参方式其实就是给C++的主函数传参,所以C++中必须有带参数的main函数;
d. 生成的exe复制到别的位置再调用时会报各种缺库的错,只要把报错的库一起复制过来即可,好像是有可以不用复制的方法,后面用到了再更新;
此方法优点:传参方便,无多余操作
缺点:单独运行exe时可以在C++中用下面的命令禁止黑窗口,但是python调用时始终弹出黑窗口,目前没找到有效的去除方法
#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
或者
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
1.2 第二种调用方式:调用c++生成的dll动态链接库
如何用VS生成dll文件就不多说了,需要注意的就是32为或64位的选择,要与python对应。
Python代码:
import ctypes
strTest = bytes(path, encoding='gbk') #path为含有中文的路径名,要以比特形式传递,使用GBK或GB2312编码
LoadCpp = ctypes.cdll.LoadLibrary("./data/Win32DLL.dll") #载入dll
print(LoadCpp.add(1,2,strTest) #调用add函数
C++代码:
extern "C" __declspec(dllimport) int add(int a, int b,char * path);//声明需要调用的函数
int add(int a, int b,char * path)
{
int c = a + b;
string strPath = path; //char* 转为字符串
cout<<strPath<<endl;
return c;
}
这种调用方式不需要有main函数,也不会有黑窗口,但不知道可移植性怎么样,后续跟进
其他类型参数的传递:
https://blog.csdn.net/MrCheny/article/details/79022973
2.C++调用python:
C++代码:
#include <Python.h>
#include<iostream>
using namespace std;
//调用python函数
Py_SetPythonHome(L"C:\\Users\\Programs\\Python\\Python37");//导入python环境
Py_Initialize(); //使用python之前,要调用Py_Initialize();这个函数进行初始化
if (!Py_IsInitialized())
{
printf("初始化失败!");
return;
}
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('H:\\pythontest')"); //修改需要调用的Python文件路径
//加载文件
PyObject* pModule = PyImport_ImportModule("cpp_py"); //需要调用的py文件名,不包括后缀
if (pModule == NULL)
{
cout << "没找到python文件" << endl;
}
//选中调用函数,返回函数指针
PyObject* pFunSetSeedPoint = PyObject_GetAttrString(pModule, "pytest");
// 输入的参数
PyObject* args = PyTuple_New(2);
PyObject* pReturnValue;
//设置参数
string OriginBmpPath = "D:/test2/bmpmask";
string OriginDcmPath = "D:/test2/dcmorigin";
cout << OriginBmpPath << endl;
PyTuple_SetItem(args, 0, Py_BuildValue("s", "D:\\test2\\dcmorigin")); //参数表
PyTuple_SetItem(args, 1, Py_BuildValue("s", "D:\\test2\\bmpmask"));
//PyTuple_SetItem(args, 0, Py_BuildValue("s", OriginDcmPath)); //以变量的形式传递字符串会报错
//PyTuple_SetItem(args, 1, Py_BuildValue("s", OriginBmpPath));
//调用函数
pReturnValue = PyObject_CallObject(pFunSetSeedPoint, args);
//转换返回值
int ret = 0;
PyArg_Parse(pReturnValue, "i", &ret); //转换返回类型
cout << "ret:" << ret << endl; //输出结果
Py_Finalize();
Python代码:
def pytest(path0,path1):
print(path0)
print(path1)
return 100