C++调用Python及间接调用Python三方库

本文详细介绍了如何在不依赖Python全局环境的情况下,通过C++程序调用Python脚本及其相关三方库。首先,需要移植Python解释器,将必要的库和文件复制到C++程序的执行目录。接着,在Visual Studio中进行相应配置。然后,通过Python API在C++中初始化Python环境并调用Python函数。最终,展示了C++调用Python函数的示例代码及其输出结果。
部署运行你感兴趣的模型镜像

本文章目的是脱离安装Python环境的前提下,由C++程序调用Python程序及Python相关三方库

 

1.移植Python解释器

Python环境的目录结构

红色部分是生成路径下解释器运行时依赖
将红色部分拷贝到C++编译主ExE路径下即可,并把需要允许的py文件页考过去(也就是.py文件需和编译生成的.exe文件放在一起)

蓝色部分是VS配置编译时依赖,需要添加到vs工程的环境中

除此之外,也可以指定环境:

读取python文件位置   

程序最终发布的时候,不需要在客户端机上安装python,只需要拷贝python文件的libs,lib库,include文件夹,dll文件夹等到安装目录下,并使用

Py_SetPythonHome((char*)strPythonLibPath.c_str());指定查找路径

2.VS配置

在vs中进行配置

3.实例

python程序

def testReturn1(s1, s2):
   s = s1+s2
   return s
 
def testReturn2(s1):
   return s1

C++程序

//***python调用***//
	//初始化python模块
	Py_Initialize();
	// 检查初始化是否成功  
	if (!Py_IsInitialized())
	{
		cout << "初始化失败" << endl;
		Py_Finalize();
	}

	PyObject *pModule= PyImport_ImportModule("helloworld");//Python文件名     
	if (!pModule) 
	{
		cout << "py文件导入失败" << endl;
		Py_Finalize();
	}
	else 
	{
		PyObject*pFunc = PyObject_GetAttrString(pModule, "testReturn1");//Python文件中的函数名  
		if (!pFunc) {
			cout << "函数导入失败" << endl;
			Py_Finalize();
		}

		PyObject *pyParams1 = PyTuple_New(2);
		PyTuple_SetItem(pyParams1, 0, Py_BuildValue("s", "hello "));
		PyTuple_SetItem(pyParams1, 1, Py_BuildValue("s", "python"));

		char * result1;
		PyObject*pArg = PyEval_CallObject(pFunc, pyParams1);//调用函数
		PyArg_Parse(pArg, "s", &result1);
		cout << result1 << endl;



		pFunc = PyObject_GetAttrString(pModule, "testReturn2");//Python文件中的函数名  
		if (!pFunc) {
			cout << "函数导入失败" << endl;
			Py_Finalize();
		}
		PyObject* pyParams3 = Py_BuildValue("(i)", 123);
		int result2;
		pArg = PyEval_CallObject(pFunc, pyParams3);//调用函数
		PyArg_Parse(pArg, "i", &result2);
		cout << result2 << endl;

	}

结果

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think>我们正在讨论Python调用DLL的替代,除了ctypes。用户已经知道ctypes,现在寻求其他选项。 根据我的知识,Python调用DLL的主要有以下几个: 1. ctypes:标准的一部分,允许调用DLL中的函数。 2. CFFI (C Foreign Function Interface):一个更现代的外部函数接口,支持调用C代码,包括DLL。它提供了两种模式:内联(ABI模式)和外部(API模式)。 3. pybind11:主要用于创建C++Python扩展,但也可以用于调用已有的DLL,不过它更侧重于将C++代码暴露给Python,而不是直接调用任意DLL。 4. SWIG (Simplified Wrapper and Interface Generator):一个通用工具,可以为多种语言(包括Python)生成绑定代码。它可以用来包装DLL中的函数,但需要编写接口文件。 5. ctypesgen:一个基于ctypes的包装器生成器,它可以解析C头文件并生成相应的Python ctypes包装代码,简化了ctypes的使用。 6. PyWin32:对于Windows平台,PyWin32提供了访问Windows API的能力,其中包含了一些调用DLL的方法(特别是系统DLL),但它主要是针对Windows的。 注意:用户的问题明确要求除了ctypes以外的,所以我们将重点放在其他上。 在这些中,CFFI是一个流行的选择,因为它支持更广泛的C语言特性,并且与Python的集成更自然。pybind11则更适合C++项目。SWIG是一个老牌工具,但配置相对复杂。ctypesgen可以简化ctypes的使用,但底层还是ctypes。 因此,我们可以推荐CFFI作为ctypes的一个现代替代方案,尤其当需要调用C代码时。另外,如果用户是在Windows平台上,PyWin32也是一个选择,但仅限于Windows系统。 我们将按照以下结构回答: 1. 介绍CFFI,并给出一个简单示例。 2. 介绍pybind11(虽然它主要用于创建扩展,但也可以用于调用DLL,不过需要额外的工作,因此可能不是最直接的选择)。 3. 简要提及SWIG和ctypesgen,以及PyWin32(针对Windows用户)。 注意:由于用户要求调用DLL,我们应确保示例是调用已编译的DLL,而不是从源代码编译。但请注意,CFFI通常推荐使用API模式(从源代码编译),不过它也支持ABI模式(直接加载DLL,类似ctypes)。 因此,我们可以展示CFFI的ABI模式来直接加载DLL。 示例:使用CFFI的ABI模式调用DLL中的函数。 步骤: 1. 安装CFFI:`pip install cffi` 2. 编写Python代码加载DLL并调用函数。 假设我们有一个DLL:`example.dll`(Windows)或`libexample.so`(Linux),其中有一个函数:`int add(int, int);` 使用CFFI的ABI模式: ```python from cffi import FFI ffi = FFI() # 加载DLL lib = ffi.dlopen("example.dll") # 在Linux上使用"./libexample.so" # 声明函数原型 ffi.cdef("int add(int a, int b);") # 调用函数 result = lib.add(1, 2) print(result) # 输出3 ``` 注意:ABI模式不需要编译,但要求函数原型与二进制接口完全匹配。 另外,pybind11通常用于创建扩展模块,而不是直接加载DLL。如果用户有一个DLL,并且想用pybind11来调用,通常需要写一个包装层。因此,对于直接调用DLL,pybind11可能不是最直接的选择。 对于SWIG,它需要编写一个接口文件(.i),然后生成Python模块。这个过程相对复杂,不适合快速调用。 ctypesgen可以自动生成ctypes包装代码,但用户需要先安装:`pip install ctypesgen`,然后通过命令行生成包装模块。例如: ctypesgen -l example -o example.py 然后就可以在Python中导入example并使用。 最后,PyWin32主要针对Windows API,如果用户需要调用Windows系统DLL(如user32.dll, kernel32.dll等),可以使用PyWin32。安装:`pip install pywin32`。示例: ```python import win32api # 调用MessageBoxA win32api.MessageBox(0, "Hello", "Title", 0) ``` 但是,对于一般的DLL,PyWin32并没有提供比ctypes更简便的方法,所以通常还是用ctypes或CFFI。 总结:推荐CFFI作为ctypes的替代方案,特别是当需要更好的类型安全和更自然的集成时。其他则根据具体场景选择。 生成相关问题: 1. CFFI与ctypes相比有什么优势? 2. 如何用pybind11创建Python扩展来调用DLL? 3. 在Windows上使用Python调用系统DLL的最佳方法是什么?</think>### Python调用DLL的替代(除ctypes外) 在Python调用DLL文件时,除了标准`ctypes`,还有以下第三方替代方案: 1. **CFFI (C Foreign Function Interface)** - 支持C语言级别的接口调用,提供更安全的类型检查和内存管理 - 支持ABI模式(直接加载DLL)和API模式(需C编译器) - 示例代码: ```python from cffi import FFI ffi = FFI() ffi.cdef("int AddNumbers(int a, int b);") # 声明函数原型 lib = ffi.dlopen("./mylib.dll") # 加载DLL result = lib.AddNumbers(3, 5) # 调用函数 ``` 2. **PyBind11** - 专注于C++Python绑定,支持自动类型转换 - 需要C++源代码编译(非直接加载DLL) - 适用于高性能场景,如科学计算[^1] - 编译示例: ```cpp #include <pybind11/pybind11.h> int add(int a, int b) { return a + b; } PYBIND11_MODULE(example, m) { m.def("add", &add); } ``` 3. **SWIG (Simplified Wrapper and Interface Generator)** - 自动化生成多种语言的绑定代码(包括Python) - 通过接口文件(.i)定义导出函数 - 工作流程: ```mermaid graph LR A[C/C++代码] --> B[SWIG接口文件] B --> C[生成包装器代码] C --> D[编译为Python模块] ``` 4. **cffi + setuptools**(组合方案) - 通过`setup.py`自动编译和打包: ```python from setuptools import setup setup( name="mylib", ext_modules=[ffi.verifier.get_extension()], install_requires=["cffi"] ) ``` ### 各方案对比 | | 直接加载DLL | 需要编译 | 语言支持 | 学习曲线 | |-----------|-------------|----------|-------------|----------| | ctypes | ✓ | ✗ | C | 低 | | CFFI | ✓ | 可选 | C | 中 | | PyBind11 | ✗ | ✓ | C++ | 高 | | SWIG | ✗ | ✓ | C/C++/其他 | 高 | > **使用建议**: > - 优先尝试**CFFI**:兼具灵活性和安全性,支持直接加载DLL > - 对C++选**PyBind11**:提供更自然的Python接口 > - 大型项目考虑**SWIG**:支持多语言绑定
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值