赞
踩
我有一个USB5538的库和头文件,并通过头文件提供了接口,我想把它更改一下,编译成python可调用的模块。
1、创建空项目
2、创建目录
1、复制文件并添加
2、添加新文件并写入
1、环境异常情况
2、配置环境以消除异常
1、二次封装代码
定义一个接口对象,调用之前的接口,并将方法写入该接口对象即可。
- #include <iostream>
- using namespace std;
- #include "usbpylib.h"
- // usbpylib.cpp : 只包括标准包含文件的源文件
- // Sys.pch 将作为预编译头
- // usbpylib.obj 将包含预编译类型信息
-
- class AutoTest {
- //private:
- public:
- //USB5538数据采集器
- HANDLE createUSB5538();
- void releaseUSB5538(HANDLE hDevice);
- void resetUSB5538(HANDLE hDevice); //复位,相当于与PC重连,等同于重新插上USB
- void getUSB5538DI_All(HANDLE hDevice, BYTE bDISts[16]); //bDISts[16]为output参数
- void setUSB5538DO_All(HANDLE hDevice, BYTE bDOSts[16]); //bDOSts[16]为input参数
- int getUSB5538DI_One(HANDLE hDevice, int iDI);
- void setUSB5538DO_One(HANDLE hDevice, int iDO, int value);
- };
-
- // TODO: 在 STDAFX.H 中
- // 引用任何所需的附加头文件,而不是在此文件中引用
-
- HANDLE AutoTest::createUSB5538()
- {
- return USB5538_CreateDevice(0);
- }
-
- void AutoTest::releaseUSB5538(HANDLE hDevice)
- {
- if (hDevice == INVALID_HANDLE_VALUE)
- {
- return;
- }
- USB5538_ReleaseDevice(hDevice);
- }
-
- void AutoTest::resetUSB5538(HANDLE hDevice)
- {
- if (hDevice == INVALID_HANDLE_VALUE)
- {
- return;
- }
- USB5538_ResetDevice(hDevice);
- }
-
- void AutoTest::getUSB5538DI_All(HANDLE hDevice, BYTE bDISts[])
- {
- if (hDevice == INVALID_HANDLE_VALUE)
- {
- return;
- }
- USB5538_GetDeviceDI(hDevice, bDISts);
- }
-
- void AutoTest::setUSB5538DO_All(HANDLE hDevice, BYTE bDOSts[])
- {
- if (hDevice == INVALID_HANDLE_VALUE)
- {
- return;
- }
- USB5538_SetDeviceDO(hDevice, bDOSts);
- }
-
- int AutoTest::getUSB5538DI_One(HANDLE hDevice, int iDI)
- {
- if (hDevice == INVALID_HANDLE_VALUE)
- {
- return -1;
- }
- BYTE bDISts[16];
- USB5538_GetDeviceDI(hDevice, bDISts);
- return bDISts[iDI];
- }
-
- void AutoTest::setUSB5538DO_One(HANDLE hDevice, int iDO, int value)
- {
- if (hDevice == INVALID_HANDLE_VALUE)
- {
- return;
- }
- BYTE bDOSts[16];
- USB5538_RetDeviceDO(hDevice, bDOSts);//回读输出状态
- bDOSts[iDO] = value;
- USB5538_SetDeviceDO(hDevice, bDOSts);
- }
-
- int main()
- {
- HANDLE obj1;
- BYTE bd[16] = { 0,0,0,0,0,1,1,1, 0,0,0,0,0,1,1,1 };
- AutoTest AutoTest1;
- //cout << "Hello World";
- obj1 = AutoTest1.createUSB5538();
- cout << "句柄是\n" << obj1 << "\n";
- AutoTest1.getUSB5538DI_All(obj1, bd);
- AutoTest1.resetUSB5538(obj1);
- AutoTest1.releaseUSB5538(obj1);
- //cout << "Hello World";
- HANDLE hDevice = AutoTest1.createUSB5538();
- if (hDevice == INVALID_HANDLE_VALUE)
- {
- cout << "create error...." << "\n";
- }
- BYTE bDOSts[16];
- BYTE bDISts[16];
- bDOSts[0] = 0;
- bDOSts[1] = 1;
- bDOSts[2] = 0;
- bDOSts[3] = 1;
- bDOSts[4] = 0;
- bDOSts[5] = 1;
- bDOSts[6] = 0;
- bDOSts[7] = 1;
- bDOSts[8] = 0;
- bDOSts[9] = 1;
- bDOSts[10] = 0;
- bDOSts[11] = 1;
- bDOSts[12] = 0;
- bDOSts[13] = 1;
- bDOSts[14] = 0;
- bDOSts[15] = 1;
- AutoTest1.setUSB5538DO_All(hDevice, bDOSts);
- AutoTest1.getUSB5538DI_All(hDevice, bDISts);
- cout << "bDISts是\n" << bDISts << "\n";
- }
2、如图,运行正常,说明对原接口的二次封装是有效的
1、基于上一篇文章,创建新文件USB5538.cpp编写如下:
- #define PY_SSIZE_T_CLEAN // 建议在包含Python.h之前总是定义PY_SSIZE_T_CLEAN。
- #include <Python.h> // 打包成python扩展所需要的头文件
-
- #include <iostream>
- using namespace std;
-
- //#ifndef _USBPYLIB_H_ // 避免头文件被多次编译
- //#define _USBPYLIB_H_
- #include "../include/usbpylib.h"
- //#endif
-
-
- // 函数的三种实现方式,C函数通常是通过将Python模块和函数名组合在一起命名的,如模块是Combinations(也是.cpp名称),函数是uniqueCombinations,组成了一个函数名
- static PyObject*
- USB5538_get(PyObject* self) // 定义功能有三种方式,详细文档(旧文档)请查阅https://www.tutorialspoint.com/python/python_further_extensions.htm
- {
- //PyLongObject one = USB5538_CreateDevice(0);
- //PyAddrPair one = USB5538_CreateDevice(0);
- //PyAnySet_Check one = USB5538_CreateDevice(0);
- //PyAnySet_CheckExact one = USB5538_CreateDevice(0);
- //PyAPI_DATA one = USB5538_CreateDevice(0);
- //PyAPI_FUNC one = USB5538_CreateDevice(0);
- //PyArena_AddPyObject one = USB5538_CreateDevice(0);
- //PyASCIIObject one = USB5538_CreateDevice(0);
- //PyBaseObject_Type one = USB5538_CreateDevice(0);
- //PyByteArrayObject one = USB5538_CreateDevice(0);
- //PyBytes_FromObject one = USB5538_CreateDevice(0);
- //PyBytesObject one = USB5538_CreateDevice(0);
- //PyObject_AsCharBuffer one = USB5538_CreateDevice(0);
- //PyObject_AsReadBuffer one = USB5538_CreateDevice(0);
- //PyObject_CallObject one = USB5538_CreateDevice(0);
- PyObject_Length one = USB5538_CreateDevice(0);
- //CompareObjectHandles one = USB5538_CreateDevice(0);
- //PyOS_sighandler_t one = USB5538_CreateDevice(0);
- //PyObject one = USB5538_CreateDevice(0);
-
- HANDLE hDevice = USB5538_CreateDevice(0); // 获取句柄
-
- cout << hDevice;
-
- BYTE bd[16] = { 0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1 };
-
- //if (hDevice == INVALID_HANDLE_VALUE)
- //{
- // return;
- //}
- BOOL a = USB5538_GetDeviceDI(hDevice, bd); // 获取设备DI状态
- USB5538_ReleaseDevice(hDevice); // 释放句柄
- return Py_BuildValue("s", "uniqueCombinations() return value (is of type 'string')");
- ;
- //if (a == true)
- //{
- // return NULL;
- //}
- //else
- //{
- // return 0;
- //};
- };
-
- /*
- 函数的三种实现方式例子:
- static PyObject *MyFunction( PyObject *self, PyObject *args ); // METH_VARARGS
- static PyObject *MyFunctionWithKeywords(PyObject *self,PyObject *args,PyObject *kw); // METH_KEYWORDS
- static PyObject *MyFunctionWithNoArgs( PyObject *self ); // METH_NOARGS
- */
-
- static char get_docs[] = "获取设备的相关信息\n"; // 随意定义的文档字符串描述
-
- // 方法映射表,方法表是一个简单的PyMethodDef结构数组
- static PyMethodDef module_methods[] = {
- {"get", (PyCFunction)USB5538_get, METH_NOARGS, get_docs},
- { NULL, NULL, 0, NULL }
- // 格式解释:{ml_name,ml_meth,ml_flags,ml_doc}
- // ml_name:这是Python解释器在Python程序中使用的函数名。
- // ml_meth:这必须是函数名。
- // ml_flags:函数的三种实现方式,上述例子中已经标明对应字段选择
- // ml_doc:可以为空值,四个选项对应的空值分别为:{ NULL, NULL, 0, NULL }
- };
-
- // 模块后面加module,比较规范。这个结构必须在模块的初始化函数中传递给解释器。初始化函数必须命名为PyInit_name(),其中name是模块的名称,并且应该是模块文件中定义的唯一非静态项
- static struct PyModuleDef USB5538module =
- {
- PyModuleDef_HEAD_INIT,
- "Combinations", /* 模块名称 */
- "usage: Combinations.uniqueCombinations(lstSortableItems, comboSize)\n", /* 模块文档*/
- -1, /* 模块的每个解释器状态的大小,如果模块在全局变量中保持状态,则为-1。*/
- module_methods /* 方法映射表 , 即需要引用定义好的引射表*/
- };
-
- // 初始化函数,之前的初始化方法 PyMODINIT_FUNC initModule() 已弃用,新文档见 https://docs.python.org/3/extending/extending.html
- PyMODINIT_FUNC PyInit_USB5538(void)
- {
- return PyModule_Create(&USB5538module); // 它返回一个模块对象,并根据模块定义中的表(PyMethodDef结构的数组)将内置函数对象插入到新创建的模块中。
- }
2、尝试进行编译
3、尝试将该文件打包成python库
新建setup.py文件写入以下内容
- from distutils.core import setup, Extension
- setup(name='USB5538', version='0.1', ext_modules=[Extension('USB5538', [r'D:\MinGW\projects\USB5538ForPython\source\USB5538.cpp' ])])
打开cmd窗口执行setup.py文件(要进入该文件目录下执行)
- python setup.py build
- python setup.py install --record files.txt
以及调用其接口,均能成功
1、将该接口改为传参对象
- #define PY_SSIZE_T_CLEAN // 建议在包含Python.h之前总是定义PY_SSIZE_T_CLEAN。
- #include <Python.h> // 打包成python扩展所需要的头文件
-
- #include <stdio.h>
-
- #include <iostream>
- using namespace std;
-
- //#ifndef _USBPYLIB_H_ // 避免头文件被多次编译
- //#define _USBPYLIB_H_
- #include "../include/usbpylib.h"
- //#endif
-
-
- // 函数的三种实现方式,C函数通常是通过将Python模块和函数名组合在一起命名的,如模块是Combinations(也是.cpp名称),函数是uniqueCombinations,组成了一个函数名
- static PyObject*
- USB5538_set(PyObject* self, PyObject* args) // 定义功能有三种方式,详细文档(旧文档)请查阅https://www.tutorialspoint.com/python/python_further_extensions.htm
- {
- //PyLongObject one = USB5538_CreateDevice(0);
- //PyAddrPair one = USB5538_CreateDevice(0);
- //PyAnySet_Check one = USB5538_CreateDevice(0);
- //PyAnySet_CheckExact one = USB5538_CreateDevice(0);
- //PyAPI_DATA one = USB5538_CreateDevice(0);
- //PyAPI_FUNC one = USB5538_CreateDevice(0);
- //PyArena_AddPyObject one = USB5538_CreateDevice(0);
- //PyASCIIObject one = USB5538_CreateDevice(0);
- //PyBaseObject_Type one = USB5538_CreateDevice(0);
- //PyByteArrayObject one = USB5538_CreateDevice(0);
- //PyBytes_FromObject one = USB5538_CreateDevice(0);
- //PyBytesObject one = USB5538_CreateDevice(0);
- //PyObject_AsCharBuffer one = USB5538_CreateDevice(0);
- //PyObject_AsReadBuffer one = USB5538_CreateDevice(0);
- //PyObject_CallObject one = USB5538_CreateDevice(0);
- PyObject_Length one = USB5538_CreateDevice(0);
- //CompareObjectHandles one = USB5538_CreateDevice(0);
- //PyOS_sighandler_t one = USB5538_CreateDevice(0);
- //PyObject one = USB5538_CreateDevice(0);
-
- int a1;
- int a2;
- int a3;
- int a4;
- int a5;
- int a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16;
- if (!PyArg_ParseTuple(args, "iiiiiiiiiiiiiiii", &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16))
- {
- //return Py_BuildValue("s", "参数输入有误,请传递全数字的列表!");
- return Py_BuildValue("s", "error!");
- }
- //return Py_BuildValue("(iiiiiiiiiiiiiiiii)", a1 + a1, a1 - a2, a1+a3);
-
- HANDLE hDevice = USB5538_CreateDevice(0); // 获取句柄
-
- //cout << hDevice << "\n";
-
- BYTE bd[16] = { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16 };
- //BYTE bd[16] = { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1 }; // 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-
- USB5538_SetDeviceDO(hDevice, bd);
-
- //BOOL DIstatus = USB5538_GetDeviceDI(hDevice, bd); // 获取设备DI状态
-
- //cout << DIstatus << "\n";
-
- USB5538_ReleaseDevice(hDevice); // 释放句柄
- //return Py_BuildValue("s", "恭喜你,在窗口打印设备句柄成功!");
- return Py_BuildValue("s", "set success!");
- };
-
- /*
- 函数的三种实现方式例子:
- static PyObject *MyFunction( PyObject *self, PyObject *args ); // METH_VARARGS
- static PyObject *MyFunctionWithKeywords(PyObject *self,PyObject *args,PyObject *kw); // METH_KEYWORDS
- static PyObject *MyFunctionWithNoArgs( PyObject *self ); // METH_NOARGS
- */
-
- //static char get_docs[] = "获取设备的相关信息\n"; // 随意定义的文档字符串描述
- static char get_docs[] = "get info of device\n"; // 随意定义的文档字符串描述
-
- // 方法映射表,方法表是一个简单的PyMethodDef结构数组
- static PyMethodDef module_methods[] = {
- {"set", (PyCFunction)USB5538_set, METH_VARARGS, get_docs},
- { NULL, NULL, 0, NULL }
- // 格式解释:{ml_name,ml_meth,ml_flags,ml_doc}
- // ml_name:这是Python解释器在Python程序中使用的函数名。
- // ml_meth:这必须是函数名。
- // ml_flags:函数的三种实现方式,上述例子中已经标明对应字段选择
- // ml_doc:可以为空值,四个选项对应的空值分别为:{ NULL, NULL, 0, NULL }
- };
-
- // 模块后面加module,比较规范。这个结构必须在模块的初始化函数中传递给解释器。初始化函数必须命名为PyInit_name(),其中name是模块的名称,并且应该是模块文件中定义的唯一非静态项
- static struct PyModuleDef USB5538module =
- {
- PyModuleDef_HEAD_INIT,
- "USB5538", /* 模块名称 这个只是python调用__name__时展示,即使写错也不会有影响*/
- //"USB5538的python接口对象,提供丰富的接口,用于操作USB5538设备\n", /* 模块文档*/
- "USB5538 of python interface\n", /* 模块文档*/
- -1, /* 模块的每个解释器状态的大小,如果模块在全局变量中保持状态,则为-1。*/
- module_methods /* 方法映射表 , 即需要引用定义好的引射表*/
- };
-
- // 初始化函数,之前的初始化方法 PyMODINIT_FUNC initModule() 已弃用,新文档见 https://docs.python.org/3/extending/extending.html
- PyMODINIT_FUNC PyInit_USB5538(void)
- {
- return PyModule_Create(&USB5538module); // 它返回一个模块对象,并根据模块定义中的表(PyMethodDef结构的数组)将内置函数对象插入到新创建的模块中。
- }
2、验证
如图,验证成功!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。