You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在VSCode的C++项目中调用.pyc文件内的Python函数

核心前提说明

你首先需要明确一个认知:.pyc是Python虚拟机专属的预编译字节码,不是可以直接被CPU执行的原生机器码,不存在完全脱离Python运行时环境直接加载.pyc执行的方案。你想要在C中调用.pyc里的函数,本质上是在C进程中嵌入Python运行时,由运行时加载执行字节码,这个方案完全可行,且调用开销很低,可以实现接近无缝的调用体验。
另外你给出的示例Python代码存在逻辑错误:py_compile.compile的执行位置在函数定义之前,且编译目标文件和函数定义所在文件不匹配,会导致生成的.pyc文件不包含目标函数,下文会给出修正后的可运行代码。

方案1:嵌入Python C API 直接加载.pyc调用(匹配你原始需求的首选方案)

这个方案不需要修改你现有的Python密码学逻辑,直接通过Python官方提供的C接口在C++中启动轻量Python解释器,加载你提前编译好的.pyc文件,直接提取函数调用即可,性能损耗极小。

实现步骤

  • 第一步:整理并编译Python代码生成有效.pyc文件
    首先把密码学逻辑单独存为源文件,再执行编译:
    密码学源文件crypto_func.py内容:
    import hashlib
    
    def generate_keys():
        public_key = "Please help me".encode("utf-8")
        alphanumeric_address = hashlib.sha256(public_key).hexdigest()
        return public_key, alphanumeric_address
    
    编译脚本compile_pyc.py内容,运行后会在同目录生成可用的crypto_func.pyc:
    import py_compile
    py_compile.compile("crypto_func.py", cfile="crypto_func.pyc")
    
  • 第二步:编写C++调用逻辑,链接Python开发库
    首先安装对应Python版本的开发包(Linux环境可通过系统包管理器安装python3-dev,Windows环境可直接从已安装的Python目录中获取头文件和库文件),之后编写调用代码:
    #include <iostream>
    #include <Python.h>
    #include <string>
    
    int main()
    {
        // 初始化Python解释器
        Py_Initialize();
        if (!Py_IsInitialized()) {
            std::cerr << "Python解释器初始化失败" << std::endl;
            return -1;
        }
    
        // 将当前目录加入模块搜索路径,确保能找到pyc文件
        PyRun_SimpleString("import sys; sys.path.insert(0, '.')");
    
        // 加载编译好的pyc模块,注意模块名不要带.pyc后缀
        PyObject* pModule = PyImport_ImportModule("crypto_func");
        if (!pModule) {
            PyErr_Print();
            std::cerr << "加载pyc模块失败,请检查Python版本与pyc编译版本是否一致" << std::endl;
            Py_Finalize();
            return -1;
        }
    
        // 提取模块中的generate_keys函数
        PyObject* pFunc = PyObject_GetAttrString(pModule, "generate_keys");
        if (!pFunc || !PyCallable_Check(pFunc)) {
            PyErr_Print();
            std::cerr << "获取目标函数失败" << std::endl;
            Py_DECREF(pModule);
            Py_Finalize();
            return -1;
        }
    
        // 调用无参数函数
        PyObject* pReturn = PyObject_CallObject(pFunc, nullptr);
        if (!pReturn) {
            PyErr_Print();
            std::cerr << "函数执行失败" << std::endl;
            Py_DECREF(pFunc);
            Py_DECREF(pModule);
            Py_Finalize();
            return -1;
        }
    
        // 解析返回值元组,提取第二个位置的地址字符串
        PyObject* pAddress = PyTuple_GetItem(pReturn, 1);
        std::string alphanumeric_address = PyUnicode_AsUTF8(pAddress);
    
        std::cout << alphanumeric_address << std::endl;
    
        // 回收Python对象引用,避免内存泄漏
        Py_DECREF(pReturn);
        Py_DECREF(pFunc);
        Py_DECREF(pModule);
    
        // 关闭Python解释器,释放资源
        Py_Finalize();
        return 0;
    }
    

注意事项

编译C程序时,链接的Python库版本必须和编译.pyc使用的Python大版本完全一致,比如Python3.10生成的.pyc无法被3.9或3.11版本的解释器加载,会报魔数校验错误。
发布程序时需要随C
程序一起分发对应Python版本的核心运行时依赖,以及pqcrypto模块的依赖文件。

方案2:不依赖Python运行时的替代方案

如果你不想在C++程序中携带Python运行时,可以选择以下几种方案实现相同的调用效果:

  • 用Cython将Python代码编译为原生动态库:通过Cython给Python代码加少量类型声明,将包括pqcrypto在内的逻辑直接转译为C/C代码,编译为系统原生的动态/静态库,C可以直接链接调用,完全不需要Python环境,运行性能接近原生C++代码,缺点是需要适配部分Python动态特性的类型声明。
  • 本地服务化调用:将Python密码学逻辑封装为本地服务,通过本地套接字、管道、gRPC等方式和C进程通信,C按照约定协议发送参数、接收返回值即可,优点是完全不侵入两边的编译环境,适配成本低,缺点是存在跨进程通信的性能开销,适合调用频率不高的场景。
  • 替换为C原生的后量子密码实现:你使用的pqcrypto模块本质是对后量子密码算法原生C实现的Python封装,可以直接替换为对应的C原生后量子密码库,完全跳过Python层,性能最好,长期维护成本最低。

内容的提问来源于stack exchange,提问作者user19316228

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 15:24:19