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

使用Cython+VS生成DLL调用时出现错误码1411的问题求助

问题:LoadLibraryA调用Cython生成的DLL时返回错误码1411

环境信息

  • 操作系统:Win11
  • IDE:Visual Studio 2022
  • Conda环境:Python=3.6、cython=0.29.33
  • 生成C文件命令:cython demo.pyx -3

涉及代码

demo.pyx

cdef public int add( int str1, int str2):
    return int(str1) + int(str2)

DLL实现代码

#include <Windows.h>
#include <Python.h>
#include "demo.h"

extern "C" _declspec(dllexport)  int  p_add(int a, int b);

int p_add(int a, int b)
{
    int p = add(a, b);
    return p;
}
    

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        Py_Initialize();
        PyInit_demo();
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        Py_Finalize();
        break;
    }
    return TRUE;
}

DLL调用代码

#include <iostream>
#include <Windows.h>

typedef int(*fun)(int, int);

int main()
{   
    fun funName = NULL;
    HMODULE hMoudle =LoadLibraryA("D:\\stduioProject\\python_gen_dll\\x64\\Release\\python_gen_dll.dll");
    {
        FreeLibrary(hMoudle);
        std::cout << GetLastError();  // error code 1411
        return -1;
    }
    funName = (fun)GetProcAddress(hMoudle, "p_add");
    if (funName == NULL)
    {
        printf("error");
        FreeLibrary(hMoudle);
        return -10;
    }
    int f = funName(2, 3);
    std::cout << f << std::endl;
    FreeLibrary(hMoudle);
}

期望调用后返回结果5,但调用LoadLibraryA时出现错误码1411,已将Python版本从3.8降至3.6测试,问题仍存在。


解决办法

1. 修复DLLMain的分支逻辑错误

DLLMain的switch case未添加break,导致DLL_PROCESS_ATTACH分支执行后直接进入DLL_PROCESS_DETACH分支,刚初始化Python就立即调用Py_Finalize(),造成DLL初始化失败。

修改后的DLLMain:

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        Py_Initialize();
        PyInit_demo();
        break; // 添加break终止当前分支
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        Py_Finalize();
        break;
    }
    return TRUE;
}

2. 修复调用代码的逻辑错误

原调用代码未判断LoadLibraryA的返回值,直接执行释放DLL并返回,无论DLL是否加载成功都会报错。

修改后的调用代码:

#include <iostream>
#include <Windows.h>

typedef int(*fun)(int, int);

int main()
{   
    fun funName = NULL;
    HMODULE hModule = LoadLibraryA("D:\\stduioProject\\python_gen_dll\\x64\\Release\\python_gen_dll.dll");
    
    // 先判断DLL是否加载成功
    if (hModule == NULL)
    {
        std::cout << "Load DLL failed, error code: " << GetLastError() << std::endl;
        return -1;
    }

    funName = (fun)GetProcAddress(hModule, "p_add");
    if (funName == NULL)
    {
        printf("GetProcAddress failed\n");
        FreeLibrary(hModule);
        return -10;
    }
    
    int f = funName(2, 3);
    std::cout << f << std::endl;
    FreeLibrary(hModule);
    return 0;
}

3. 确保编译环境与Python版本匹配

  • 确认Visual Studio编译的DLL位数(x64)与Python 3.6位数完全一致(均为64位或均为32位),若Python是32位,需将VS项目改为x86平台编译。
  • 在VS项目设置中配置Python路径:
    • 包含目录添加Python环境的include路径(例如C:\Users\<你的用户名>\anaconda3\envs\<环境名>\include)
    • 库目录添加Python环境的libs路径(例如C:\Users\<你的用户名>\anaconda3\envs\<环境名>\libs)
    • 链接器输入添加python36.lib(Python3.6对应的库文件)

4. 确保Python依赖DLL可被找到

运行调用程序时,需保证Python 3.6的python36.dll在系统PATH中,或放置在调用程序的同一目录下,否则DLL加载时会因找不到Python依赖而初始化失败。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 10:25:18