繁体   English   中英

嵌入 Python 的 C++:如果未安装 Python,则崩溃

[英]C++ with Python embedding: crash if Python not installed

我在 Windows 上开发,我到处搜索都没有找到任何人谈论这种事情。

我在我的桌面上制作了一个 C++ 应用程序,它使用 MSVC 嵌入了 Python 3.1。 我链接了 python31.lib 并将 python31.dll 与可执行文件一起包含在应用程序的运行文件夹中。 效果很好。 我的扩展和嵌入代码绝对有效并且没有崩溃。

我将运行文件夹发送给未安装 Python 的朋友,应用程序在脚本设置阶段为他崩溃了。

几个小时前,我在安装了 Python 2.6的笔记本电脑上试用了该应用程序。 我得到了和我朋友一样的崩溃行为,通过调试发现是 Py_Initialize() 调用失败了。

我在我的笔记本电脑上安装了 Python 3.1,但没有更改应用程序代码。 我运行它并且运行完美。 我卸载了 Python 3.1,应用程序再次崩溃。 我在我的应用程序中放入代码以从本地 python31.dll 动态链接,以确保它正在使用它,但我仍然遇到崩溃。

我不知道解释器需要的不仅仅是 DLL 来启动还是什么。 我一直无法找到这方面的任何资源。 Python 文档和其他指南似乎从未解决过如何分发使用 Python 嵌入的 C/C++ 应用程序,而无需用户在本地安装 Python。 我知道这在 Windows 上比在 Unix 上更严重,但我已经看到许多在本地嵌入 Python 的 Windows C/C++ 应用程序,但我不确定它们是如何做到的。

除了 DLL,我还需要什么? 为什么我安装 Python 时它可以工作,然后当我卸载它时它就停止工作了? 听起来应该如此微不足道; 也许这就是为什么没有人真正谈论它的原因。 不过,我真的无法解释如何处理这个崩溃问题。

非常感谢你提前。

除了 pythonxy.dll 之外,您还需要整个 Python 库,即 lib 文件夹的内容,加上扩展模块,即 DLLs 文件夹的内容。 没有标准库,Python 甚至无法启动,因为它试图找到 os.py(在 3.x 中;string.py 在 2.x 中)。 在启动时,它会导入一些模块,特别是 site.py。

它在不同的位置搜索标准库; 在您的情况下,它最终会在注册表中找到它。 之前,使用可执行文件名称(通过 Py_SetProgramName 设置)试图找到地标; 它还会检查文件 python31.zip,该文件应该是标准库的压缩副本。 它还检查环境变量 PYTHONHOME。

您可以自由地从库中删除不需要的东西; 有多种工具可以静态计算依赖关系(尤其是 modulefinder)。

如果你想尽量减少文件的数量,你可以

  1. 将所有扩展模块静态链接到您的 pythonxy.dll,甚至将 pythonxy.dll 静态链接到您的应用程序
  2. 使用冻结工具; 这将允许将标准库的字节码链接到您的 pythonxy.dll 中。
  3. (替代 2.)使用 pythonxy.zip 作为标准库。

好的。 如果您不想压缩,请将 Python26\DLLs & Python26\lib 复制到您的 exe 目录,如下所示:

.\myexe.exe       
.\python26.dll
.\Python26\DLLs
.\Python26\lib

然后使用 Py_SetPythonHome() API 设置 PYTHONHOME。 显然,此 API 不在 Py_Initialize()之前的“允许”调用列表中;

下面在 Windows 上为我工作(未安装Python):

#include "stdafx.h"
#include <iostream>
#include "Python.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
   char pySearchPath[] = "Python26";
   Py_SetPythonHome(pySearchPath);
   Py_Initialize();
   PyRun_SimpleString("from time import time,ctime\n"
                     "print 'Today is',ctime(time())\n");
   //cerr << Py_GetPath() << endl;
   Py_Finalize();

    return 0;
}

很好,搜索路径是相对于 exe 的。 Py_GetPath 可以告诉你它在哪里寻找模块。

我想为可能仍然遇到问题的其他人添加一些额外的信息,就像我一样。 我最终能够使用用户 sambha 提出的方法使我的应用程序正常工作,即:

Program Files (x86)\
    MyApplicationFolder\
        MyApplication.exe
        python27.dll
        Python27\
            DLLs\ (contents of DLLs folder)
            Lib\ (contents of Lib folder)

...有一个重要的补充:我还需要安装 MSVCR90.DLL。 我使用的是 Python 2.7,显然 python27.dll 需要 MSVCR90.DLL(可能还有其他 MSVC*90.DLL)。

我通过从http://www.microsoft.com/en-us/download/details.aspx?id=29下载、安装和运行“vcredist_x86.exe”包解决了这个问题。 我认为,虽然我不确定,但您至少需要在 Win7 上这样做,而不是像过去那样简单地将 MSVC*90.DLL 放在 your.exe 旁边。 微软安装程序在 Win7 下以特殊方式放置文件并注册它们。

我也尝试了 .zip 文件方法,但没有用,即使安装了 MSVCR90.DLL。

Python 标准库的压缩包适用于 Python27。

我压缩了 Lib 和 dll 的内容,并确保没有额外的 python27-subfolder 或 Lib 或 dll 子文件夹。 即只是一个名为 python27.zip 的 zip 包含所有文件。

我复制了那个 zip 和 python27.dll 以及可执行文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM