使用CPython完成对linux编译库.so 封装提供windows c#调用

本人一直从事windows开发,linux系统也经常接触过,部署Docker什么的,但是还没有再linux环境下做过开发。最近跟第三方对接。对方提供了c++的linux编译库 .so文件,这时有人说让第三方重新编译dll。但是我还是尝试再linux环境下,通过CPython对多第三方接口进行封装,然后使用python编写WebAPI部署Docker服务,这样c#也就能正常调用了。虽然过程曲折,但是完美的解决了问题。

第一步,开发环境装备:

1、基本的linux系统环境。我使用的Centos,另外虚拟机也可以。不要安装什么图像化界面等,我再这方面踩了不少坑。浪费太多时间。然后新建用户user,密码123456;假定IP:192.168.1.12

2、windows系统安装xshell或者windows terminal  ,然后还需要对于我们c#开发来说最熟悉的visual studio code 。

3、打开windows terminal(xshell)也可以。输入 ssh [email protected] 回车后输入密码:123456。不出意外连接linux环境。

4、安装c++编译器,linux下常见的gcc ,clang。yum install gcc。安装python ,yum install python。具体还需要什么环境根据项目来定。

5、打开我们的IDE,visual studio code,是的,我们以后的开发都是这个IDE即可,不要再linux系统下进行。安装扩展Remote-ssh。如果不会自己百度搜索vscode  扩展安装吧。

6、然后shift+ctrl+p  输入remote-ssh 选择Remote-SSH:Connect to host ,然后选择 Add new shh host。

7、输入ssh [email protected]。下面OUTPUT 会提示让你输入密码:123456.回车后,左侧出现如下图列表,恭喜你完成基本的开发环境设置了。

使用CPython完成对linux编译库.so 封装提供windows c#调用_第1张图片

二、C编写Python扩展

1、开发环境有了,这样就编写Python扩展了吗?

当然首先安装c++扩展,还需要针对c++编译的一些配置。还要需要用到下面三个配置文件

这个三个文件再新建helloworld.cpp后,再调试模式下,点击运行,或者直接F5会弹出提示,让选择一个编译方式,本人使用的g++(开始选择了gcc,后面遇到一个坑)。会自动创建。

c_cpp_properties.json 关于cpp的基本配置,需要变动的是:includePath。这里要包含项目中需要使用到的相关依赖,比如gcc,python等。

launch.json 程序执行配置。

tasks.json 程序编译配置。

其中:保证tasks.json中的label 的值和launch.json中的preLaunchTask值一致。不然会报错。

最后保证程序编译正常,且运行后输出hello world 。如果出现问题请自行百度,或者留言。

2、C写一个python扩展需要四个步骤:

  • 包含头文件Python.h
  • 你需要作为python接口的C函数
  • 一个将你的函数映射为python接口的映射表
  • 一个初始化函数

a、

#include 

b、C函数:三种形式

static PyObject *MyFunction( PyObject *self, PyObject *args );

static PyObject *MyFunctionWithKeywords(PyObject *self,  PyObject *args, PyObject *kw);

static PyObject *MyFunctionWithNoArgs( PyObject *self );

c、方法映射表就是PyMethodDef结构的数组

struct PyMethodDef {
   char *ml_name;
   PyCFunction ml_meth;
   int ml_flags;
   char *ml_doc;
};
static PyMethodDef module_methods[] = {
   { "func", (PyCFunction)module_func, METH_VARARGS, NULL },
   { NULL, NULL, 0, NULL }
};
ml_name: 这是暴露给python程序的函数名;
ml_meth: 这是指向函数的指针,也就是真正函数定义的地方;
ml_flags: 这告诉python解析器想用三种函数签名的哪一种,一般来说,它的值是METH_VARARGS;如果你想传入关键字参数的话,也可以与MET_KEYWORDS进行或运算;当然,如果你不想接受任何参数的话,可以给其赋值为METH_NOARGS;
ml_doc: 这是函数的文档字符串,如果你不想写的话,直接给其赋值为NULL。

d、初始化函数

初始化函数必须被命名为initModuleName,这里ModuleName表示你的模块名。

是不是很简单。也没那么复杂,有了这四个模块。你再python里面就可以调用。

3、再三个c函数中,有2个带参数的,当然也是我们会经常用的,那怎么传参或返回值呢?

a、获取python参数

解析无关键字的参数用 PyArg_ParseTuple方法:

int PyArg_ParseTuple(PyObject* tuple,char* format,...)

解析带有关键字的参数用 PyArg_ParseTupleAndKeywords方法:

int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], ...)

遇到错误返回0,返回别的数字代表正确。

b、返回python

Python C 函数的返回值都是PyObject*类型的(错误返回NULL),如果不想返回任何值,就是用宏Py_RETURN_NONE。

PyObject* Py_BuildValue(char* format,...)

c、参数缩写对应:

Code

C type

Meaning

c

char

A Python string of length 1 becomes a C char

d

double

A Python float becomes a C double

f

float

A Python float becomes a C float

i

int

A Python int becomes a C int

l

long

A Python int becomes a C long.

L

long long

A Python int becomes a C long long

O

PyObject*

Gets non-NULL borrowed reference to Python argument.

s

char*

Python string without embedded nulls to C char*.

s#

char*+int

Any Python string to C address and length.

t#

char*+int

Read-only single-segment buffer to C address and length.

u

Py_UNICODE*

Python Unicode without embedded nulls to C.

u#

Py_UNICODE*+int

Any Python Unicode C address and length.

w#

char*+int

Read/write single-segment buffer to C address and length.

z

char*

Like s, also accepts None (sets C char* to NULL).

z#

char*+int

Like s#, also accepts None (sets C char* to NULL).

(…)

as per …

A Python sequence is treated as one argument per item.

|

 

The following arguments are optional.

:

 

Format end, followed by function name for error messages.

;

 

Format end, followed by entire error message text.

4、写好的c程序怎么把发布给python调用呢?

  需要使用distutils模块,来发布我们的cpp程序。

1、定义个setup.py脚本文件

from distutils.core import setup, Extension
setup(name="exampleAPP", version="1.0", ext_modules=[Extension("example", ["example.cpp"])])

2、编译 ,编译后的文件为.so。

python setup.py build

三、Python 编写WebAPI

1、python 调用cpython扩展

首先 装备python开发环境,设置sdk相关环境变量。进入python 使用 import example。

导入成功后再python脚本中使用from example import example

然后根据cpp里面的方法映射表来调用即可。

2、python封装webAPI 。

网上资料很多,自行百度吧。

3、python webAPI服务部署Docker。

网上资料很多,自行百度吧。

四、C# 调用WebAPI

使用httpClient 即可。具体自行百度。

 

整个项目中对于我来说,最陌生的还是基于linux开发,总认为Linux开发就必须再Linux系统中操作,觉得操作很不方便,做开发应该也会很麻烦。通过这个项目才明白,是可以再windows系统下做linux开发的,通过ssh ,linux开发也很简单。

你可能感兴趣的:(linux)