使用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对应的库文件)
- 包含目录添加Python环境的
4. 确保Python依赖DLL可被找到
运行调用程序时,需保证Python 3.6的python36.dll在系统PATH中,或放置在调用程序的同一目录下,否则DLL加载时会因找不到Python依赖而初始化失败。
内容的提问来源于stack exchange,提问作者Xi Zhu
相关产品推荐
相关产品推荐

