java通过c调用python
来源:互联网 发布:手机用户mac绑定错误 编辑:程序博客网 时间:2024/06/06 02:08
最近在做一个项目,主要是用到python下的一个库(sympy),之前通过java通过jython调用python,速度达不到要求,后面把python单独拿出来,做成一个本地服务,通过socket与java通信,速度上去了,但是很不方便
现在是通过c调用python,然后利用java调用c(这方面的资料网上很多,下面主要说说细节问题)1,因为java调用c,要是使用64位,所以对应的python必须下载64位版的,
2,然后在vs生成dll文件的时候,要设置为64位,我是用vs2010写的
3.注意引入python的库文件和头文件
生成dll的工程:
下面是头文件 mydll.h代码
#ifndef _MYDLL_H_#define _MYDLL_H_#include <string>#include <stdio.h>#include <stdlib.h>#include <sstream>#include "jni.h"#ifdef __cplusplusextern "C" {#endifJNIEXPORT jstring JNICALL Java_sympy_SympyJavaJNI_invokingSympy__Ljava_lang_String_2Ljava_lang_String_2 (JNIEnv *, jobject, jstring, jstring);JNIEXPORT jstring JNICALL Java_sympy_SympyJavaJNI_invokingSympy__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2 (JNIEnv *, jobject, jstring, jstring, jstring);#ifdef __cplusplus}#endif#endif //_MYDLL_H_注:jni.h是Jni自动生成的,奇怪的东西是jni自动生成的,直接复制过来用就是了,这里主要定义了2个接口函数,第一个参数是对应python里面的函数名,第二个参数和第三个函数是该对应函数的参数,(如果该函数只要1个参数,就是调用的第一个,利用函数重载完成),
testdlladd.cpp代码清淡,主要是实现上面的2个接口(我承认我的文件命名很奇怪)
注释中的Add函数就是c调用python中的东西,其中pDict是全局变量,后面会提到
// testdlladd.cpp : 定义 DLL 应用程序的导出函数。//#include "stdafx.h"#include "mydll.h"using namespace std;string int2str(int &);/*char* Add(char* a, char* b){printf("pDict:%d\n",pDict);PyObject *pFunc, *pArgs, *pRetVal; pFunc = PyDict_GetItemString(pDict, "add"); if ( !pFunc||!PyCallable_Check(pFunc) ) { printf("can't find function [add]"); getchar(); return 0; } // 参数进栈 pArgs = PyTuple_New(2); // PyObject* Py_BuildValue(char *format, ...) // 把C++的变量转换成一个Python对象。当需要从 // C++传递变量到Python时,就会使用这个函数。此函数 // 有点类似C的printf,但格式不同。常用的格式有 // s 表示字符串, // i 表示整型变量, // f 表示浮点数, // O 表示一个Python对象。//string a = int2str(plus1);//string b= int2str(plus2); PyTuple_SetItem(pArgs, 0, Py_BuildValue("s",a)); PyTuple_SetItem(pArgs, 1, Py_BuildValue("s",b)); // 调用Python函数 pRetVal = PyObject_CallObject(pFunc, pArgs);char* res=PyString_AsString(pRetVal); return res;}*/JNIEXPORT jstring JNICALL Java_sympy_SympyJavaJNI_invokingSympy__Ljava_lang_String_2Ljava_lang_String_2 (JNIEnv *env, jobject _obj, jstring funcName, jstring param1) { const char* fName = env->GetStringUTFChars(funcName,0); const char* parameter = env->GetStringUTFChars(param1,0); PyObject *pFunc, *pArgs, *pRetVal; pFunc = PyDict_GetItemString(pDict, fName); if ( !pFunc||!PyCallable_Check(pFunc) ) { printf("can't find function %s",fName); return 0; } // 参数进栈 pArgs = PyTuple_New(1); // PyObject* Py_BuildValue(char *format, ...) // 把C++的变量转换成一个Python对象。当需要从 // C++传递变量到Python时,就会使用这个函数。此函数 // 有点类似C的printf,但格式不同。常用的格式有 // s 表示字符串, // i 表示整型变量, // f 表示浮点数, // O 表示一个Python对象。//string a = int2str(plus1);//string b= int2str(plus2); PyTuple_SetItem(pArgs, 0, Py_BuildValue("s",parameter));//PyTuple_SetItem(pArgs, 1, Py_BuildValue("s",b)); // 调用Python函数 pRetVal = PyObject_CallObject(pFunc, pArgs); char* res=PyString_AsString(pRetVal); env->ReleaseStringUTFChars(funcName,fName); env->ReleaseStringUTFChars(param1,parameter); return env->NewStringUTF(res); } JNIEXPORT jstring JNICALL Java_sympy_SympyJavaJNI_invokingSympy__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2 (JNIEnv * env, jobject _obj, jstring funcName, jstring param1, jstring param2) { const char* fName = env->GetStringUTFChars(funcName,0); const char* p1 = env->GetStringUTFChars(param1,0); const char* p2 = env->GetStringUTFChars(param2,0); PyObject *pFunc, *pArgs, *pRetVal; pFunc = PyDict_GetItemString(pDict, fName); if ( !pFunc||!PyCallable_Check(pFunc) ) { printf("can't find function %s",fName); return 0; } // 参数进栈 pArgs = PyTuple_New(2); // PyObject* Py_BuildValue(char *format, ...) // 把C++的变量转换成一个Python对象。当需要从 // C++传递变量到Python时,就会使用这个函数。此函数 // 有点类似C的printf,但格式不同。常用的格式有 // s 表示字符串, // i 表示整型变量, // f 表示浮点数, // O 表示一个Python对象。 PyTuple_SetItem(pArgs, 0, Py_BuildValue("s",p1)); PyTuple_SetItem(pArgs, 1, Py_BuildValue("s",p2)); // 调用Python函数 pRetVal = PyObject_CallObject(pFunc, pArgs); char* res=PyString_AsString(pRetVal); env->ReleaseStringUTFChars(funcName,fName); env->ReleaseStringUTFChars(param1,p1); env->ReleaseStringUTFChars(param2,p2); return env->NewStringUTF(res); }string int2str(int &i) {string s;stringstream ss(s);ss << i;return ss.str();}
stdafx.h文件代码清单
这里定义了3个全局变量,主要是因为我们要频繁调用python里的库(1秒估计要几百次吧,还没考虑高并发),所以第一次加载的时候,先把DLL文件加载的里面,避免每次调用python的时候,都去加载那个dll文件,效率就十分十分十分十分的慢
#ifndef _STDAFX_H_#define _STDAFX_H_#include "targetver.h"#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的信息// Windows 头文件:#include <windows.h>#include<stdio.h>#include "jni.h"#include "jni_md.h"#include <Python.h>extern PyObject *pDict,*pName,*pModule;#endif
下面是dllmain.cpp,dll的入口函数,我觉得该写个destroy函数
// dllmain.cpp : 定义 DLL 应用程序的入口点。#include "stdafx.h"PyObject *pDict=NULL;PyObject *pName=NULL;PyObject *pModule=NULL;static int init(void){<span style="white-space:pre"></span>// 初始化Python //在使用Python系统前,必须使用Py_Initialize对其 //进行初始化。它会载入Python的内建模块并添加系统路 //径到模块搜索路径中。这个函数没有返回值,检查系统 //是否初始化成功需要使用Py_IsInitialized。<span style="white-space:pre"></span> Py_Initialize(); // 检查初始化是否成功 if ( !Py_IsInitialized() ) {<span style="white-space:pre"></span>printf("Py_Initialize() error"); return 0; } // 载入名为pytest的脚本(注意:不是pytest.py) pName = PyString_FromString("sympyInvoke"); pModule = PyImport_Import(pName); if ( !pModule ) { printf("can't find pytest.py"); return 0; } pDict= PyModule_GetDict(pModule); if ( !pDict ) {<span style="white-space:pre"></span><span style="white-space:pre"></span>printf("can't find Method!!"); return 0; } <span style="white-space:pre"></span>}BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved<span style="white-space:pre"></span> ){<span style="white-space:pre"></span> <span style="white-space:pre"></span>switch (ul_reason_for_call)<span style="white-space:pre"></span>{<span style="white-space:pre"></span>case DLL_PROCESS_ATTACH:init();printf("DLL in");break; <span style="white-space:pre"></span>case DLL_THREAD_ATTACH:<span style="white-space:pre"></span>case DLL_THREAD_DETACH:<span style="white-space:pre"></span>case DLL_PROCESS_DETACH:printf("DLL out");break;<span style="white-space:pre"></span>}<span style="white-space:pre"></span>return TRUE;}
至于Jni,怎么调用这个dll,网上一查一大堆,就不在赘述了!
这样生成的dll文件就可以用在我们的java工程中去啦!(注意要安装python64位)
0 0
- java通过c调用python
- Java通过JYTHON调用python
- python通过swig调用c程序举例
- Python 通过Jpype调用Java类
- 【Python】Python通过ctypes调用C动态链接库
- java通过jni调用C程序
- Java通过JNI调用C/C++函数
- JAVA通过JNI调用C函数Demo
- Android C 通过JNI 调用JAVA
- java通过jni调用c库
- AndroidJNI 通过C/C++调用JAVA
- java通过JNA调用c语言dll
- Java通过JNI调用C语言
- Java 通过 JNI 调用 C/C++ 类库
- Java通过jni调用c语言方法
- Learning Python -- Java 通过JyThon调用Python实现的规则
- 通过SWIG封装C/C++代码被Python调用
- python通过swig调用c++dll时指针的用法
- AppCrashView
- tomcat管理账户配置
- 今生只爱整数
- 可变函数定义及使用
- 广告常用概念小结
- java通过c调用python
- Ubuntu Linux下安装Oracle JDK
- 有关UITableView的contentSize、contentInset和contentOffset
- ios中的变量和属性
- document.all
- VC 保存数据
- Raw-OS源码分析之事件标志
- POJ 3767 I Wanna Go Home 最短路
- GameServer