【问题标题】:Python XDECREF failing on 64bit mingwPython XDECREF 在 64 位 mingw 上失败
【发布时间】:2019-12-06 12:58:42
【问题描述】:

我正在使用以下代码从 C 调用 python 方法:

#include "Python.h"

char *find_site(void)
{
    char *app_site_dir = 0;
    PyObject *module = 0;
    PyObject *result = 0;
    PyObject *module_dict = 0;
    PyObject *func = 0;

    module = PyImport_ImportModule((char *)"Site"); /* new ref */
    if (module == 0)
    {
    PyErr_Print();
    printf("Couldn't find python module Site\n");
    goto out;
    }
    printf("module = %p\n", module);
    module_dict = PyModule_GetDict(module); /* borrowed */
    if (module_dict == 0)
    {
    PyErr_Print();
    printf("Couldn't find read python module Site\n");
    goto out;
    }
    func = PyDict_GetItemString(module_dict, "find_site"); /* borrowed */
    if (func == 0)
    {
    PyErr_Print();
    printf("Couldn't find Site.find_site\n");
    goto out;
    }
    result = PyEval_CallObject(func, NULL); /* new ref */
    if (result == 0)
    {
    PyErr_Print();
    printf("Couldn't run Site.find_site\n");
    goto out;
    }
    else if (result == Py_None)
    {
    printf("Couldn't find site\n");
    goto out;
    }
    printf("result = %p\n", result);
    app_site_dir = PyString_AsString(result); /* borrowed */
    if (app_site_dir == 0)
    {
    PyErr_Print();
    printf("Couldn't read result from Site.find_site\n");
    goto out;
    }
    app_site_dir = strdup(app_site_dir); /* keep in our own memory */
    if (*app_site_dir)
    {
    printf("Found Site at %s\n", app_site_dir);
    }
    else
    printf("Could not find Site\n");
out:;
    printf("result = %p decref\n", result);
    Py_XDECREF(result);
    printf("module = %p module\n", module);
    Py_XDECREF(module);

    return app_site_dir;
}

int main(int argc, char **argv)
{
    Py_Initialize();
    char *site = find_site();
    printf("Site = %s\n", site);
    free(site);
}

python代码是

import os

def find_site():
    return os.path.abspath(".")

(在完整的应用程序中,这更复杂,但这个简化的例子说明了问题)

这是在 linux 上使用 mxe.cc 交叉编译的,如下所示: i686-w64-mingw32.static-c++ -I/usr/local/opt/mxe.master/usr/x86_64-w64-mingw32.static/include/python2.7 -o py32.exe py.cc -lpython27

它按预期在 Windows 上运行(来自 Ubuntu shell)

module = 028BC710
result = 0283D6B0
Found Site at \\wsl$\Ubuntu\home\dl
result = 0283D6B0 decref
module = 028BC710 decref
Site = \\wsl$\Ubuntu\home\dl

但是当编译为 64 位时 x86_64-w64-mingw32.static-c++ -I/usr/local/opt/mxe.master/usr/x86_64-w64-mingw32.static/include/python2.7 -o py64.exe py.cc -lpython27

运行失败:

module = 0000000002750408
result = 0000000000E62EF0
Found Site at \\wsl$\Ubuntu\home\dl
result = 0000000000E62EF0 decref

Python 调用成功,返回值并打印,但resultXDECREF 失败,程序弹了出来,没有其他输出。

在这两种情况下,libpython 都是使用从目标 Windows 机器复制的 .dll 以及 pexports 和 dlltool 来创建 .a:例如

pexports-0.47/pexports python27.dll > python27.def
i686-w64-mingw32.static-dlltool  --dllname python27.dll --def python27.def --output-lib libpython2.7.a

我的问题可能出在哪里?

【问题讨论】:

  • ... 如果 python 的返回值为 return "C:/Test/Path" 它可以工作。如果您添加 test2 = testreturn test2 它会失败。如果你说test2 = "".join(c for c in path)return test2 它会失败。如果你设置 path2 = "C:/Test/Pathreturn test2 就可以了
  • 使用Py_REFCNT [在C 代码中] 显示return "c:/test" 的值为2,但return test 的值为1
  • 在 python 2.7.17, 2.7.0, 2.6, 3.8 中完全相同的问题。
  • 适用于 64 位 linux (Ubuntu/Bionic)
  • 通过在我的应用程序中重新定义 Py_DECREF 宏:#define Py_DECREF(op) do { if (--op->ob_refcnt == 0) fprintf(stderr, "DECREF %s %d %p %d %s %p\n", __FILE__, __LINE__, op, Py_SIZE(op), Py_TYPE(op)->tp_name,Py_TYPE(op)->tp_dealloc ); fflush(stderr); } while(0) 输出如下行:DECREF vardef_file.cc 1601 0000000009F3C728 0 generator 0000000000000000 似乎显示 tp_dealloc 是一个空指针。

标签: python mingw


【解决方案1】:

找到并修复,pyconfig.h 对于 mingw 64 位使用不正确,并且 Py_ssize_t 的 sizeof 错误。

https://bugs.python.org/issue39001

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 2016-01-31
    相关资源
    最近更新 更多