android 动态库 如何编译<sys/types.h>,利用python3的ctypes库实现动态库so的调用

核心关注点在于通过python来处理C函数的入参与出参

动态库和调用的系统版本要匹配:

dll动态库需要在windows环境下运行,32bit的so动态库需要在32bit的linux环境下面调用,64bit的so动态库需要在64bit的linux环境下面调用

否则,报错:

Traceback (most recent call last):

File "cdll_so_s1ap_initialUE.py", line 85, in

sotest = cdll.LoadLibrary(os.getcwd()+ "/look.so")

File "/usr/local/lib/python3.6/ctypes/__init__.py", line 426, in LoadLibrary

return self._dlltype(name)

File "/usr/local/lib/python3.6/ctypes/__init__.py", line 348, in __init__

self._handle = _dlopen(self._name, mode)

OSError: /home/look.so.so: wrong ELF class: ELFCLASS32

原因:

Python 的 ctypes 要使用 C 函数,需要先将 C 编译成动态链接库的形式,即 Windows 下的 .dll 文件,或者 Linux 下的 .so 文件。先来看一下 ctypes 怎么使用 C 标准库。

Windows 系统下的 C 标准库动态链接文件为 msvcrt.dll (一般在目录 C:\Windows\System32 和 C:\Windows\SysWOW64 下分别对应 32-bit 和 64-bit,使用时不用刻意区分,Python 会选择合适的)

Linux 系统下的 C 标准库动态链接文件为 libc.so.6 (以 64-bit Ubuntu 系统为例, 在目录 /lib/x86_64-linux-gnu 下

一、动态库编译(C语言):

#ifdef _WIN_

#define DllExport __declspec( dllexport )

#else

#define DllExport __attribute ((visibility("default")))

#endif

DllExport int lookup(BYTE *in, WORD in_len, DWORD dwStartBit, BYTE *out, DWORD *out_len, BYTE bDir, CHAR *key)

二、导出符号表(eg:Linux):

nm -D look.so

在符号表中,可以看到第一步中C语言的导出函数。

三、出参处理(BYTE *out):

Python 默认的 string 是不可变的,所以不能传递 string 到一个 C 函数去改变它的内容,所以需要使用 create_string_buffer,对应 Unicode 字符串,要使用 create_unicode_buffer,

C常规参数类型与ctypes、python类型对应关系表如下:

25d46cfba5cd52fc647ce5c3214b1bcf.png

四、实例源码:

#! /usr/bin/env/python

# _*_ encoding : utf-8 _*_

from ctypes import *

import platform

import os, re

def getSpace(level):

space='\n'

for i in range(level):

space=space+' '

return space

# 格式化 XML 字符串#

def printXml(xml_str):

#xml_list=xml_str.split('([>])')

new_xml_list=""

# head=xml_str[0:9]

# xml_str=xml_str[9:]

xml_list=re.split(r'([>])',xml_str)

xml_list = ["".join(i) for i in zip(xml_list[0::2],xml_list[1::2])]

level=0

for node in xml_list:

if(re.match(r'',node)):

new_xml_list=new_xml_list+new_xml_list+node

continue

elif(re.match(r'',node)):

new_xml_list=new_xml_list+getSpace(level)+node

level=level+1

continue

elif(re.match(r'',node)):

level=level-1

new_xml_list=new_xml_list+getSpace(level)+node

continue

elif(re.match(r'',node)):

new_xml_list=new_xml_list+getSpace(level)+node

elif(re.match(r'.+',node)):

new_xml_list=new_xml_list+node

level=level-1

else:

print(node)

# print(new_xml_list)

return new_xml_list

def writeXML(outputstrt, xmlFileName):

fileHandle = open(xmlFileName, 'w',encoding="utf_8_sig")

fileHandle.write('')

fileHandle.close()

fileHandle = open(xmlFileName, 'a',encoding="utf_8_sig")

fileHandle.write(outputstrt + '\n\n')

fileHandle.close()

if __name__ == '__main__':

# key = "123456789" # 暂时随便写一个

# key_str = "E7 AB 8B E6 B0 91 E5 9B BD E4 BB AC E6 88 91 E4 B8 AD E4 BA BA E4 B8 BA E4 BA 86 E5 BB BA E4 B8" # 暂时随便写一个

key_str = '07 41 01 08 49 06 11 99 09 20 00 00 05 F3 72 40 30 00 00 05 52 00 D0 11 D1'

bitstream_Str = '01 00 01 38 00 00 00 00 12 00 30 10 80 08 64 10 91 99 00 32 11 F2 02 01 05 83 01 01'

# 输入码流的预处理

input_len = len(bitstream_Str.replace(" ", '')) // 2

bitstream_list = bitstream_Str.split(' ')

input = (c_char * input_len)()

for i in range(input_len):

input[i] = int(bytes(bitstream_list[i], encoding='utf-8'),16)

print(int(bytes(bitstream_list[i], encoding='utf-8'),16))

in_p = bytes(bytearray(input))

key_len = len(key_str.replace(" ", '')) // 2

key_list = key_str.split(' ')

key = (c_char * key_len)()

for i in range(key_len):

key[i] = int(bytes(key_list[i], encoding='utf-8'),16)

print(int(bytes(key_list[i], encoding='utf-8'),16))

key_p = bytes(bytearray(key))

# 打开 .so 文件

sotest = cdll.LoadLibrary(os.getcwd()+ "/XML.so")

sotest.argtypes = [c_char_p, c_ushort, c_uint, c_ubyte, c_uint, c_ubyte, c_ubyte, c_ubyte, c_char_p, c_char_p, c_ubyte, c_char_p] # 声明C函数的所有入参

sotest.restype=[c_int] # 声明C函数的返回值类型

buffer = create_string_buffer(8000000) # 创建可用于修改的出参

buffer_len = c_int() # 定义出参的长度变量

print("\n--------------------------------so打印结果输出-------------------------------------\n")

result = sotest.PubDecode(in_p, #BYTE *in

input_len, #WORD in_len

0, #DWORD dwStartBit+

9, #BYTE bModType

1325056, #DWORD msgType

3, #BYTE msgVersion

0, #BYTE bDir 1 - receive 0 - send

0, #BYTE bNetType

buffer, #BYTE *out

byref(buffer_len), # DWORD *out_len

0, #BYTE isAnony

key_p) #CHAR *key

print("\n--------------------------------py调试结果输出-------------------------------------\n")

print(os.getcwd()+ "/XML.so")

print("\n******--------input--------******")

print("input_len: " + str(input_len))

print("bitstream_Str: " + bitstream_Str.replace(" ", ''))

print(in_p)

print(bitstream_list)

print("\n******--------result--------******")

print("result: %d 0-ok 1-failed" % result)

print("\n******--------output--------******")

print("out_len: " + str(buffer_len.value))

print("\n------------------")

print(str(buffer.value).replace(r'\n', '').replace(r'\r', '').split("'")[1])

print("\n--------------------------------结果输出到文件-------------------------------------\n")

writeXML(printXml(str(buffer.value).replace(r'\n', '').replace(r'\r', '').split("'")[1]), 'xmlpcode.txt')

五、reference:

python调用第三方动态库(附代码) - 官方文档

https://blog.csdn.net/chongtong/article/details/81566868

Python调用DLL动态链接库——ctypes使用

https://www.cnblogs.com/FHC1994/p/11421229.html

Python调用c/c++动态库(一)

https://blog.csdn.net/giveaname/article/details/89811783

python调用C/C++程序出现的32位和64位的问题

https://blog.csdn.net/budding0828/article/details/89344888

Python利用ctypes实现按引用传参

https://www.cnblogs.com/douzujun/p/10822031.html

Python实例浅谈之三Python与C/C++相互调用

https://www.cnblogs.com/apexchu/p/5015961.html

python在 linux上调用.so文件

https://blog.csdn.net/python_tty/article/details/44495659

python关于ctypes使用char指针与bytes相互转换的问题

https://www.cnblogs.com/hjbf/p/11969521.html

Python中bytes与字符串的相互转化

https://www.cnblogs.com/haitaoli/p/10587257.html

Python工作笔记-往dll中传入char*类型的参数并且如何接收char*的值 - 利用了ctypes库中的string_at

https://blog.csdn.net/qq78442761/article/details/83058756

使用 ctypes 进行 Python 和 C 的混合编程

https://www.cnblogs.com/gaowengang/p/7919219.html

将博客搬至CSDN —— python 调用 so 库 需要注意的地方

https://blog.csdn.net/github_37157365/article/details/80494733

通过ctype由python向C语言传递char *,获取新结果

https://blog.csdn.net/weixin_38825407/article/details/101709466

python调用c/c++ (入参出参为指针)

https://www.cnblogs.com/taurusfy/p/9321883.html

https://www.cnblogs.com/kgtone/p/9601918.html

任务备忘(已经完成):用python写一个格式化xml字符串的程序

Python字符串前面加u,r,b的含义

https://blog.csdn.net/winfred_hua/article/details/86079353

格式化XML字符串

https://www.cnblogs.com/kgtone/p/9601918.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值