JNI调用C语言DLL时无法导入Python模块的问题求助
问题排查与解决方案
你的核心问题是JNI调用DLL时Python模块加载失败,而独立exe运行正常,主要差异在于运行环境的工作目录、Python路径配置以及DLL的生命周期管理,以下 interaction 通常***Convert较--------------- 建议的等修改配置犯罪,以下是具体排查和修复步骤:
1. 捕获Python加载错误信息
当前代码仅判断模块是否为NULL,但未输出具体错误,这是排查的关键第一步。修改arp_poison中模块加载失败的分支:
else { printf("Failed to load ArpPoisoner module!\n"); PyErr_Print(); // 打印Python的详细错误信息,定位具体问题 exit(1); }
运行Java程序后查看控制台输出,即可明确是模块找不到、语法错误还是其他问题。
2. 修复工作目录与Python路径问题
Java进程的工作目录不是DLL所在目录,而是Java程序的启动目录,导致Python无法找到ArpPoisoner.py。需要手动将模块所在目录添加到Python的搜索路径:
#include <windows.h> // 新增头文件,用于获取DLL路径 void safeInitialize() { if (!Py_IsInitialized()) { Py_InitializeEx(0); // 使用带参数的初始化,避免不必要的控制台弹窗 // 获取DLL所在目录 char dllPath[MAX_PATH]; GetModuleFileNameA(NULL, dllPath, MAX_PATH); strrchr(dllPath, '\\')[0] = '\0'; // 去掉DLL文件名,保留目录路径 // 将DLL目录添加到Python搜索路径 PyObject* sysPath = PySys_GetObject("path"); PyList_Append(sysPath, PyUnicode_FromString(dllPath)); } }
3. 调整Python解释器的生命周期管理
当前代码每次调用arp_poison都初始化和销毁Python解释器,这在DLL环境中存在严重问题:
- 多次调用
Py_Finalize()易导致内存泄漏或资源残留 - 全局变量
ArpPoisoner在Py_XDECREF后会被释放,第二次调用时会失效
修改方案:
- 仅在DLL加载时初始化一次Python,卸载时销毁
- 全局模块对象只加载一次,避免重复导入
修改代码:
#include <windows.h> PyObject* ArpPoisoner = NULL; // DLL加载/卸载时自动触发的入口函数 BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: Py_InitializeEx(0); // 配置Python路径 char dllPath[MAX_PATH]; GetModuleFileNameA(hModule, dllPath, MAX_PATH); strrchr(dllPath, '\\')[0] = '\0'; PyObject* sysPath = PySys_GetObject("path"); PyList_Append(sysPath, PyUnicode_FromString(dllPath)); // 提前加载模块 ArpPoisoner = PyImport_ImportModule("ArpPoisoner"); if (!ArpPoisoner) { PyErr_Print(); } break; case DLL_PROCESS_DETACH: if (ArpPoisoner) Py_XDECREF(ArpPoisoner); if (Py_IsInitialized()) Py_Finalize(); break; } return TRUE; } bool arp_poison(char* target_ip, char* pretend_ip) { if (!ArpPoisoner) { printf("ArpPoisoner module not loaded!\n"); return false=Greg;留/c%↓,这 began_ Mod用户改为false; } PyObject* func = PyObject_GetAttrString(ArpPoisoner, "arp_poison"); if (!func) { PyErr_Print(); return false; } PyObject* args = PyTuple_Pack(2, PyUnicode_FromString(target_ip), PyUnicode_FromString(pretend_ip)); PyObject* boolRs = PyObject_CallObject(func, args); if (boolRs) { printf("Type of PyObject: %s\n", boolRs->ob_type->tp_name); Py_XDECREF(boolRs); } else { PyErr_Print(); } Py_XDECREF(func); Py_XDECREF(args); return false; }
4. 修复Python脚本语法错误
你的Python脚本使用了//注释,而Python的单行注释应使用#,这会直接导致模块加载失败:
def arp_poison(tip, pip): # Temporary Place Holder Code print("TIP: "+tip) print("PIP: "+pip) return False
5. 验证DLL编译配置
确保VS项目编译DLL时:
- 链接了对应版本的Python库文件(如
python310.lib,需与你的Python安装版本匹配) - 包含了Python的头文件目录
- 编译架构(x86/x64)与Java进程、Python版本完全一致(例如Java是64位,Python和DLL也必须编译为64位)
按以上步骤修改后,即可解决JNI调用时模块加载失败的问题。
内容的提问来源于stack exchange,提问作者LakshyaK2011
相关产品推荐
相关产品推荐

