栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

python ctypes调用C++ dll,arry(数组)的相关操作

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python ctypes调用C++ dll,arry(数组)的相关操作

@[TOC](python ctypes调用C++ dll,arry(数组)的相关操作)

前言

本人新手python一枚,最近工作中需要用到python 调用C++库,一个数组调用,花费了太多时间,遂决定记录下来,防止忘记。

调用原型:

#MAX_ID_LEN_PER_THREAD 65
DWORD QueryConnectedDeviceList(int *iChNum,char szDevList[][MAX_ID_LEN_PER_THREAD],int itimeout)

C++下使用:

char devList[32][65]={0};
int iChNum=0;
res=QueryConnectedDeviceList(&iChNum,devList,30);
使用python提供的ctypes库调用C++,如果想直接看结果,请拉到最后。 这部分讨论 ctypes.Arry的个人理解

首先是官方的资料,读完一脸懵逼。ctypes

class ctypes.Array(*args)
Abstract base class for arrays.

The recommended way to create concrete array types is by multiplying any ctypes data type with a positive integer. Alternatively, you can subclass this type and define _length_ and _type_ class variables. Array elements can be read and written using standard subscript and slice accesses; for slice reads, the resulting object is not itself an Array.

_length_
A positive integer specifying the number of elements in the array. Out-of-range subscripts result in an IndexError. Will be returned by len().

_type_
Specifies the type of each element in the array.

Array subclass constructors accept positional arguments, used to initialize the elements in order.

然后网上找了一些资料,尝试了一下,如下是可以生成一个数组

def make_array(ctype,arr)->ctypes.Array:
    return (ctype * len(arr))(*arr) 

第一次我想到的是用char*的数组调用dll,能成功调用并放回正确值,但当我访问数组的值却发生了异常。
代码如下:

# -*- coding: utf-8 -*-
from ctypes import *
def make_array(ctype,arr):
    return (ctype * len(arr))(*arr)

lib = CDLL("./UCCommonLib.dll")  # 加载动态库,LoadLibrary
# note:ctypes调用和返回值默认为int --》即没有特别需要,DWORD返回类型不需要特定指定返回类型
# 如果类型不为int,则必须指定类型
lib.QueryConnectedDeviceList.argtypes =[POINTER(c_int),c_char_p * 32,c_int]
ChNum = c_int(0)
arr = [b""]*32
szDevList = make_array(c_char_p,arr)
print(szDevList)
print(szDevList[0])
res = lib.QueryConnectedDeviceList(byref(ChNum),szDevList,30)
print("res:",res)
print("ChNum:",ChNum.value)
print(szDevList)
print(szDevList[0])
print("调用完成")

运行结果:

<__main__.c_char_p_Array_32 object at 0x00E393D0>
b''
res: 0
ChNum: 2
<__main__.c_char_p_Array_32 object at 0x00E393D0>

Process finished with exit code -1073741819 (0xC0000005)

调用C++ dll前szDevList[0]是可以访问,调用后再打印szDevList[0]就报错了,无奈pycharm在ctypes下不能用debug模式,就只能自己去猜问题出在哪里。

1.怀疑是make_array方法没能生成一个以65 char字节对齐的数组,因为我生成的是一个32数组大小的char *。

按照这个想法,我直接生成一个 65 * 32 *sizeof(char) 大小的数组去调用。

# -*- coding: utf-8 -*-
from ctypes import *
def make_array(ctype,arr):
    return (ctype * len(arr))(*arr)

lib = CDLL("./UCCommonLib.dll")  # 加载动态库,LoadLibrary
lib.QueryConnectedDeviceList.argtypes =[POINTER(c_int),c_char_p ,c_int]
ChNum = c_int(0)
szDevList = create_string_buffer(b"", 65*sizeof(c_char) * 32)
print(szDevList)
res = lib.QueryConnectedDeviceList(byref(ChNum),szDevList,30)  
print(szDevList)
print(szDevList.raw)
print(szDevList.value)
print("调用完成")

结果:


QueryConnectedDeviceList
find device info:COM-1|3
find device info:COM-1|4
szDevList:COM-1|3
szDevList:COM-1|4

b'COM-1|3x00x00x00x00x00x00x00x00COM-1|4x00x00x00x00' # 此次省略掉若干输出
b'COM-1|3'
调用完成

我本身需要的是 szDevList包含 COM-1|3、COM-1|4两个信息,如果我使用

print(szDevList[65].raw)
output:
Traceback (most recent call last):
  File "ucdebugger.py", line 69, in 
    print(szDevList[65].raw)
AttributeError: 'bytes' object has no attribute 'raw'

这又会让我进入另个坑中。

再次静下心来,认真分析

def make_array(ctype,arr):
    return (ctype * len(arr))(*arr)
 
 __main__.c_char_p_Array_32 object at 0x00E393D0
 ctypes.c_char_Array_2080 object at 0x01819418

我得到了重要的结论:
def make_array(ctype,arr)->ctypes.Array
ctype * len(arr) 返回一个ctypes类型的数组, (*arr)则是构造这个类型的一个实例

c_int * 5 返回一个 c_long_Array_5类型,即 int[5]
list = [1,2,3,4,5]
(c_int * 5)(*list) 即构造了一个实列对象,即 int a[5] = {1,2,3,4,5}

按照这个想法,我开始构造二维数组。

arrType = (c_char * 65) * 32
print(arrType)
output:
c_char_Array_65_Array_32

看到这个输出,就知道该怎么做了,以下是完整代码

# -*- coding: utf-8 -*-
import ctypes
from ctypes import *

# note:ctypes调用返回值默认为int --》即没有特别需要,DWORD返回类型不需要特定指定返回类型
def make_array(ctype,arr)->ctypes.Array:
    return (ctype * len(arr))(*arr)

lib = CDLL("./UCCommonLib.dll")  # 加载动态库,LoadLibrary
arrType = (c_char * 65) * 32
print(arrType)
lib.QueryConnectedDeviceList.argtypes =[POINTER(c_int),arrType,c_int]
ChNum = c_int(0)
str65 = create_string_buffer(b"0", 65*sizeof(c_char))
arr = [str65]*32
szDevList = make_array(c_char*65,arr)
print(szDevList)
res = lib.QueryConnectedDeviceList(byref(ChNum),szDevList,30)  
print("res:",res)
print("ChNum:", ChNum.value)
# print(values.raw)
for one in szDevList:
    print(one.value)
print("调用完成")

结果:


<__main__.c_char_Array_65_Array_32 object at 0x01EB95C8>
QueryConnectedDeviceList
find device info:COM-1|3
find device info:COM-1|4
szDevList:COM-1|3
szDevList:COM-1|4
res: 0
ChNum: 2
b'COM-1|3'
b'COM-1|4'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
b'0'
调用完成

Process finished with exit code 0

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/737929.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号