C DLL和Python CTypes在Release/Debug中的返回不同

2024-09-28 23:43:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个DLL,它的存在仅仅是为了向Python公开一些打印机API函数。其中一种方法如下:

extern "C" DOEXPORT const wchar_t* P_EnumPrintersW() {
    DWORD dwneeded(0), dwreturned(0);
    BOOL test = ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
        NULL,
        4,
        NULL,
        0,
        &dwneeded,
        &dwreturned);
    std::vector<byte> printbuf;
    printbuf.resize(dwneeded);
    test = ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
        NULL,
        4,
        &printbuf[0],
        printbuf.size(),
        &dwneeded,
        &dwreturned);
    PRINTER_INFO_4* print4 = static_cast<PRINTER_INFO_4*>((LPVOID) &printbuf[0]);
    wstring result;
    for (DWORD i = 0; i < dwreturned; ++i) {
        result += L",";
        result += print4[i].pPrinterName;
    }
    return result.c_str();
}

这通常如预期的那样工作,我可以在python世界中使用以下代码调用它:

^{pr2}$

我通常希望dllopts看起来像这样:

^{3}$

是的,我希望空白字符串作为第一个条目,这个DLL的全部原因是为了处理具有语言支持的宽字符名称的打印机名称。在调试模式下构建DLL之前,这一切都很好。然后,我得到的不是我期望的结果,而是:

[u'\udddd\udddd\udddd...']

只有一个值,每个字符都是\udddd。哇?是不是ctypes在调试模式下不知道如何处理dll的副作用?这是因为dll的内存映射处于调试模式的影响吗?我可以附加到我的python进程(通过它,调用它的dll)并在返回之前验证result的值,它看起来是正确的,但它不能进入我的python程序。我有点不知所措。在


Tags: test打印机enumresultprinternulldll调试模式
1条回答
网友
1楼 · 发布于 2024-09-28 23:43:54

不能返回由局部变量管理的指针。当wstring result超出范围时,使用result.c_str()返回的指针是未定义的行为。在

解决方案示例:

  1. 你可以让p_EnumPrintersW函数接收一个指针, 使用相应的大小信息,更新指向的内存 ,然后返回指针。这个 在调用函数之前,必须在Python中分配内存。

  2. 另一种解决方案是让函数返回指向 马洛塞德记忆。你必须添加另一个API,执行 对应的free

相关问题 更多 >