本站分享:AI、大数据、数据分析师培训认证考试,包括:Python培训Excel培训Matlab培训SPSS培训SAS培训R语言培训Hadoop培训Amos培训Stata培训Eviews培训

python编程__C语言调用Python模块和Python中调用C函数

python培训 cdadata 3653℃

python编程__C语言调用Python模块和Python中调用C函数

一、C语言中调用python模块
代码c_py.c如下:
#include <Python.h>
#include <stdio.h>
int main()
{
    //初始化python
Py_Initialize();
    if (!Py_IsInitialized()) {
printf(“Python_Initialize failed\n”);
return 1;
}

PyObject *pModule = NULL;
PyObject *pFunc   = NULL;

PyRun_SimpleString(“import sys”);                                   //直接执行python语句
PyRun_SimpleString(“sys.path.append(&apos;./&apos;)”);

pModule = PyImport_ImportModule(“ss”);
if (pModule == NULL) {
printf(“can&apos;t import module\n”);
return 1;
}

    pFunc   = PyObject_GetAttrString(pModule, “hello”);
PyEval_CallObject(pFunc,NULL);
Py_Finalize();

return 0;
}

其中调用的python ss.py模块代码如下:
#!/usr/bin/python2.6

def hello():
print “hello world”;

编译:
     gcc -Wall -g c_py.c -o c_py  -I/usr/include/python2.6 -lpython2.6
运行结果如下:

[chenbaihu@build17 code_test]$ ./c_py

hello world
二、python中调用c函数
在C调用Python模块时需要初始化Python解释器,导入模块等,但Python调用C模块却比较简单,下面还是以helloWorld.c 和 main.py 做一说明:
 
(1)编写C代码,helloWorld.c代码很简单,只是输出“Hello World!”:
(2)将编写的C代码编译成动态链接库的形式,具体命令:
注意:
     这里是使用gcc编译的,如果使用g++编译,就需要使用extern “C” {}了
此时在当前目录下就生成了libhello.so 的动态链接库:
 
(3)在main.py中导入动态链接库,并调用C函数
这里的ctypes是Python的一个外部库,提供和C语言兼容的数据类型,以方便的调用C编译的静态库和动态库中的函数, 在此可以很肯定的说,ctypes中可定对C的数据类型进行了转换,使用时只需import ctypes ,然后导入动态库即可。
 
(4)在终端下输入Python main.py, 运行结果:
打印出helloWorld.c中的内容, 说明Python调用C模块成功!
 
简单举例,在python中调用标准库
from ctypes import *
libc = CDLL(&apos;/lib64/libc.so.6&apos;);
str = “hello world”;
var = 5;
libc.printf(“%s\t%d\n”, str, var);
运行结果:
hello world     5
详细的在python中调用动态库,及C++程序方法,参数传入与参数传出:
arr.c代码:

#include <vector>
#include <string>
#include <stdio.h>

extern “C” {
int arrinit();
const char* arrtest(int version, const char *main_conf);
}

std::vector<std::string> vec;

int arrinit()
{
vec.push_back(“aaaaa”);
vec.push_back(“bbbb”);
vec.push_back(“cccccc”);
vec.push_back(“dddddd”);
printf(“%s\n”,”arrinit 4″);
return 4;
}

const char* arrtest(int version, const char *main_conf)
{
printf(“%d\t%s\n”, version, main_conf);
return vec[version].c_str();

}
编译:
      g++ -fPIC -shared arr.c -o arr.so
测试arr.py程序:
from ctypes import *

arr = CDLL(&apos;./arr.so&apos;)

ret = arr.arrinit();                                                        # 直接调用动态库so中的函数
print ret;

ARRTESTFUN = arr.arrtest                                           # 将so中的函数映射到python中的函数,后面声明输入值列表和返回值列表
ARRTESTFUN.argtypes  = [c_int, c_char_p]
ARRTESTFUN.restype   = c_char_p

conf = ARRTESTFUN(2, “/home/s/cloudkill/etc/main_conf.json”);               #  调用
print conf;

再举例:
     ctypes提供了另外的思路来调用c程序。首先ctypes是python的标准库,所以如果用ctypes你不需要额外的其他的东西。ctypes让你可以在python直接写代码加载c的链接库so文件来调用,就是说如果你用so文件而没有源文件的话,你仍然可以用ctypes去调用。

from ctypes import *

f = &apos;mytest.so&apos;
cdll.LoadLibrary(f)
api = CDLL(f)
api.add.argtypes = [c_int, c_int]
api.add.restype   = c_int
api.sub.argtypes = [c_int, c_int]
api.sub.restype   = c_int

print api.add(3, 2)
print api.sub(3, 2)
有点像在python中去写接口文件,由于是python的标准库,所以这种方式用的还是蛮多的。

在这里我们可以看到python中ctypes中的类型与c语言中的类型存在一一对应的关系,具体关系如下:
当然boo类型是:   c_bool
在项目中对加解密库进行封装给python使用:
 
__NETPROTO_PY_MODULE_NAME = &apos;__netproto_pydll&apos;
try:
from os.path import abspath
from os.path import dirname
curf_path = dirname(abspath(__file__))
 globals()[__NETPROTO_PY_MODULE_NAME] = ctypes.cdll.LoadLibrary(curf_path + &apos;/netproto_pymodule.so&apos;)
#print “Load Module: “, globals()[__NETPROTO_PY_MODULE_NAME]
except Exception, e:
print “Load Module <netproto_pymodule.so> Error: “, e
sys.exit(-1)
class NS(object):
__NETPROTO_PY_MODULE_NAME = &apos;__netproto_pydll&apos;
__dllmod = globals()[__NETPROTO_PY_MODULE_NAME]
# main_main
    Main = __dllmod.main_main

 # CreatePackerHandler
    CreatePackerHandler = __dllmod.CreatePackerHandler
    CreatePackerHandler.argtypes = [ctypes.c_int, ctypes.c_char_p]
    CreatePackerHandler.restype = ctypes.c_int

 # DeletePackerHandler
    DeletePackerHandler = __dllmod.DeletePackerHandler
    DeletePackerHandler.argtypes = [ctypes.c_int]
    DeletePackerHandler.restype = ctypes.c_bool

# AddEncryptKey
    AddEncryptKey = __dllmod.AddEncryptKey
    AddEncryptKey.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p]
    AddEncryptKey.restype = ctypes.c_bool

# Pack func
    Pack = __dllmod.Pack
    Pack.argtypes = [ctypes.c_int, ctypes.c_char_p, ctypes.c_int, ctypes.c_int, ctypes.c_int]
    Pack.restype = ctypes.c_char_p

    # UnPack func
    UnPack = __dllmod.UnPack
    UnPack.argtypes = [ctypes.c_int, ctypes.c_char_p]
    UnPack.restype = ctypes.c_char_p

 
NS = NS()
具体使用:
def Main():
NS.Main()

def CreatePackerHandler(version, type):
try:
if type!=PACKER_SERVER and type!=PACKER_CLIENT:
print “Un-supported type: “, repr(type)
return None
if version not in (2,9,10):
print “Un-supported version: “, repr(version)
return None
id = NS.CreatePackerHandler(version, type)
__Handler_Map[id] = (version, type)
return id
except Exception, e:
print “CreatePackerHandler Error: “, e
return None

def DeletePackerHandler(handler_id):
try:
version, type = __Handler_Map.get(handler_id, (None, None))
if version is None or type is None:
raise RuntimeError(“Handler Id <%s> NOT Exists.”%handler_id)
ret_bool = NS.DeletePackerHandler(handler_id)
if ret_bool:
__Handler_Map.pop(handler_id, None)
return ret_bool
except Exception, e:
print “DeletePackerHandler Error: “, e
return False

 
上面netproto_pymodule.so中为python定义的函数接口:
#ifdef __cplusplus
extern “C” {
int  main_main(void);
int  CreatePackerHandler(int version, const char* role );
bool DeletePackerHandler(int handler_id);
bool AddEncryptKey(int handler_id, int key_id, const char* key_type, const char* key1_p, const char* key2_p);
const char*   Pack(int handler_id, char* raw_data_p, int var1, int var2, int key_id);
const char* UnPack(int handler_id, char* packed_data_p);
}
#endif

转载请注明:数据分析 » python编程__C语言调用Python模块和Python中调用C函数

喜欢 (0)or分享 (0)