Java通过JNI调用python文件出现错误:Java JNI调用的接口文件运行出错!
运行Java报错:
"D:\Program Files\Java\jdk17\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.2.2\lib\idea_rt.jar=55810:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.2.2\bin" -Dfile.encoding=UTF-8 -classpath D:\Users\AppData\IdeaProjects\demo_callpy\target\classes;D:\maven-jar\org\python\jython-standalone\2.7.0\jython-standalone-2.7.0.jar;D:\maven-jar\org\springframework\boot\spring-boot-starter-web\3.0.2\spring-boot-starter-web-3.0.2.jar;D:\maven-jar\org\springframework\boot\spring-boot-starter-json\3.0.2\spring-boot-starter-json-3.0.2.jar;D:\maven-jar\com\fasterxml\jackson\core\jackson-databind\2.14.1\jackson-databind-2.14.1.jar;D:\maven-jar\com\fasterxml\jackson\core\jackson-annotations\2.14.1\jackson-annotations-2.14.1.jar;D:\maven-jar\com\fasterxml\jackson\core\jackson-core\2.14.1\jackson-core-2.14.1.jar;D:\maven-jar\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.14.1\jackson-datatype-jdk8-2.14.1.jar;D:\maven-jar\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.14.1\jackson-datatype-jsr310-2.14.1.jar;D:\maven-jar\com\fasterxml\jackson\module\jackson-module-parameter-names\2.14.1\jackson-module-parameter-names-2.14.1.jar;D:\maven-jar\org\springframework\boot\spring-boot-starter-tomcat\3.0.2\spring-boot-starter-tomcat-3.0.2.jar;D:\maven-jar\org\apache\tomcat\embed\tomcat-embed-core\10.1.5\tomcat-embed-core-10.1.5.jar;D:\maven-jar\org\apache\tomcat\embed\tomcat-embed-el\10.1.5\tomcat-embed-el-10.1.5.jar;D:\maven-jar\org\apache\tomcat\embed\tomcat-embed-websocket\10.1.5\tomcat-embed-websocket-10.1.5.jar;D:\maven-jar\org\springframework\spring-web\6.0.4\spring-web-6.0.4.jar;D:\maven-jar\org\springframework\spring-beans\6.0.4\spring-beans-6.0.4.jar;D:\maven-jar\io\micrometer\micrometer-observation\1.10.3\micrometer-observation-1.10.3.jar;D:\maven-jar\io\micrometer\micrometer-commons\1.10.3\micrometer-commons-1.10.3.jar;D:\maven-jar\org\springframework\spring-webmvc\6.0.4\spring-webmvc-6.0.4.jar;D:\maven-jar\org\springframework\spring-aop\6.0.4\spring-aop-6.0.4.jar;D:\maven-jar\org\springframework\spring-context\6.0.4\spring-context-6.0.4.jar;D:\maven-jar\org\springframework\spring-expression\6.0.4\spring-expression-6.0.4.jar;D:\maven-jar\org\springframework\boot\spring-boot-starter\3.0.2\spring-boot-starter-3.0.2.jar;D:\maven-jar\org\springframework\boot\spring-boot\3.0.2\spring-boot-3.0.2.jar;D:\maven-jar\org\springframework\boot\spring-boot-autoconfigure\3.0.2\spring-boot-autoconfigure-3.0.2.jar;D:\maven-jar\org\springframework\boot\spring-boot-starter-logging\3.0.2\spring-boot-starter-logging-3.0.2.jar;D:\maven-jar\ch\qos\logback\logback-classic\1.4.5\logback-classic-1.4.5.jar;D:\maven-jar\ch\qos\logback\logback-core\1.4.5\logback-core-1.4.5.jar;D:\maven-jar\org\apache\logging\log4j\log4j-to-slf4j\2.19.0\log4j-to-slf4j-2.19.0.jar;D:\maven-jar\org\apache\logging\log4j\log4j-api\2.19.0\log4j-api-2.19.0.jar;D:\maven-jar\org\slf4j\jul-to-slf4j\2.0.6\jul-to-slf4j-2.0.6.jar;D:\maven-jar\jakarta\annotation\jakarta.annotation-api\2.1.1\jakarta.annotation-api-2.1.1.jar;D:\maven-jar\org\springframework\spring-core\6.0.4\spring-core-6.0.4.jar;D:\maven-jar\org\springframework\spring-jcl\6.0.4\spring-jcl-6.0.4.jar;D:\maven-jar\org\yaml\snakeyaml\1.33\snakeyaml-1.33.jar;D:\maven-jar\org\springframework\boot\spring-boot-devtools\3.0.2\spring-boot-devtools-3.0.2.jar;D:\maven-jar\org\slf4j\slf4j-api\2.0.6\slf4j-api-2.0.6.jar com.example.demo.JNITest.Demo
Exception in thread "main" java.lang.UnsatisfiedLinkError: 'void com.example.demo.JNITest.Test.initModule()'
at com.example.demo.JNITest.Test.initModule(Native Method)
at com.example.demo.JNITest.Demo.main(Demo.java:16)
pycharm里面的结构:
先对pyx文件:
cythonize -i -3 JavaTest.pyx可以正常运行
python setup.py build_ext --inplace无报错
这个是setup.py文件
```python
from distutils.extension import Extension
from distutils.core import setup
from Cython.Build import cythonize
sourcefiles = ['Test.pyx', r'D:\Users\wangxiaofei\MYPYCHARM\JniPy\main.c']
extensions = [Extension("libTest", sourcefiles,
include_dirs=[r'D:\Program Files\Java\jdk17\include',
r'D:\Program Files\Java\jdk17\include\win32'
r'D:\Users\Python39\include',
],
library_dirs=[r'D:\Users\Python39\Lib'],
libraries=['python39'])]
setup(
ext_modules = cythonize("Test.pyx")
)
这个是Test.py:
FileName: Test.pyx
# 示例代码:将输入的字符串转变为大写
def logic(param):
print('this is a logic function')
print('param is [%s]' % param)
return param.upper()
# 接口函数,导出给Java Native的接口
def JNI_API_TestFunction(param):
print("enter JNI_API_test_function")
result = logic(param)
print("leave JNI_API_test_function")
return result
这个是main.c:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <Python.h>
#include <stdio.h>
#ifndef _Included_main
#define _Included_main
#ifdef __cplusplus
extern"C" {
#endif
#if PY_MAJOR_VERSION < 3
# define MODINIT(name) init ## name
#else
# define MODINIT(name) PyInit_ ## name
#endif
PyMODINIT_FUNC MODINIT(Test)(void);
JNIEXPORT void JNICALL Java_Test_initModule
(JNIEnv *env, jobject obj) {
PyImport_AppendInittab("Test", MODINIT(Test));
Py_Initialize();
PyRun_SimpleString("import os");
PyRun_SimpleString("__name__ = \"__main__\"");
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
PyObject* m = PyInit_Test_Test();
if (!PyModule_Check(m)) {
PyModuleDef *mdef = (PyModuleDef *) m;
PyObject *modname = PyUnicode_FromString("__main__");
m = NULL;
if (modname) {
m = PyModule_NewObject(modname);
Py_DECREF(modname);
if (m) PyModule_ExecDef(m, mdef);
}
}
PyEval_InitThreads();
}
JNIEXPORT void JNICALL Java_Test_uninitModule
(JNIEnv *env, jobject obj) {
Py_Finalize();
}
JNIEXPORT jstring JNICALL Java_Test_testFunction
(JNIEnv *env, jobject obj, jstring string)
{
constchar* param = (char*)(*env)->GetStringUTFChars(env, string, NULL);
static PyObject *s_pmodule = NULL;
static PyObject *s_pfunc = NULL;
if (!s_pmodule || !s_pfunc) {
s_pmodule = PyImport_ImportModule("Test");
s_pfunc = PyObject_GetAttrString(s_pmodule, "JNI_API_testFunction");
}
PyObject *pyRet = PyObject_CallFunction(s_pfunc, "s", param);
(*env)->ReleaseStringUTFChars(env, string, param);
if (pyRet) {
jstring retJstring = (*env)->NewStringUTF(env, PyUnicode_AsUTF8(pyRet));
Py_DECREF(pyRet);
return retJstring;
} else {
PyErr_Print();
return (*env)->NewStringUTF(env, "error");
}
}
#ifdef __cplusplus
}
#endif
#endif
这个是Test.java:
```java
package com.example.demo.JNITest;
// FileName: Test.java
public class Test {
public native void initModule();
public native void uninitModule();
public native String testFunction(String param);
}
```c
public class Demo {
static
{
System.load("D:\\Users\\wangxiaofei\\MYPYCHARM\\JniPy\\Test.cp39-win_amd64.pyd");
}
public static void main(String[] args) {
Test tester = new Test();
tester.initModule();
String result = tester.testFunction("this is called from java");
tester.uninitModule();
System.out.println(result);
}
}