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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 05:13:19