Python调用C语言函数

2021-09-20  本文已影响0人  何亮hook_8285

ctype说明

ctypes是Python的一个外部库,可以通过Ctypes调用C/C++语言的函数。

ctypes与C语言类型

ctypes type c type python type
c_bool _Bool bool(1)
c_char char 1-character bytes objecg
c_wchar wchar_t 1-character string
c_ubyte unsigned char int
c_short short int
c_ushort unsigned short int
c_int int int
c_long long int
c_ulong unsigned long int
c_longlong __int64 or long long int
c_ulonglong unsigned __int64 or unsigned long long int
c_size_t size_t int
c_ssize_t ssize_t or py_ssize_t int
c_float float float
c_double double float
c_longdouble long double float
c_char_p char *(NUL terminated) byte object or None
c_wchar_p wchar_t *(Nul terminated) string or None
c_void_p void * int or None

传递数字类型

C语言代码

extern "C" LIB void testNumber(int number, float score, bool isFlag)
{
    printf("%d %f %d ", number, score, isFlag);
    if (isFlag)
    {
        printf("isFlag true");
    }
    else
    {
        printf("isFlag false");
    }
}

python代码

# 引入ctypes模块
from ctypes import *

# 加入dll 动态库
lib= CDLL("test")
try:
    lib.testNumber(c_int(101), c_float(88.1), True)
except Exception as ex:
    print("testNumber error",ex)
    pass

#等于用户输入,程序不退出
input()

传递普通字符类型

C语言代码

LIB void testStr(const char *str,int size) 
{
    printf("testStr :%s %d", str, size);
}

python代码

# 引入ctypes模块
from ctypes import *

# 加入dll 动态库
lib= CDLL("test")
try:
    #将字符串转换 bin
    str1=b"hello world"
    lib.testStr(str1, c_int(len(str1)))
except Exception as ex:
    print("testStr error",ex)
    pass

#等于用户输入,程序不退出
input()

传递宽字符类型

C语言代码

LIB void testWStr(const wchar_t *str, int size)
{
    printf("testWStr :%ls %d", str, size);
}

python代码

# 引入ctypes模块
from ctypes import *

# 加入dll 动态库
lib= CDLL("test")
try:
    #将字符串转换 bin
    wstr1="hello world"
    lib.testWStr(wstr1, c_int(len(wstr1)))
except Exception as ex:
    print("testStr error",ex)
    pass

#等于用户输入,程序不退出
input()

传递可修改字符串

C语言代码

LIB void testStrBuff(char *str,int size) 
{
    str[0] = 'a';
    str[1] = 'b';
    str[2] = '\0';//字符串结尾
    printf("testStrBuff :%s %d", str, size);
}

python代码

# 引入ctypes模块
from ctypes import *

# 加入dll 动态库
lib= CDLL("test")
try:
    #可修改字符串
    buf=create_string_buffer(100)
    lib.testStrBuff(buf,c_int(len(buf)))
    print("in python buffer = ",buf.raw,buf.value,len(buf),sep="\n")
except Exception as ex:
    print("testStr error",ex)
    pass

#等于用户输入,程序不退出
input()

传递数组

C语言代码

//传递数组类型
LIB void testArray(int *arr,int size)
{
    for(int i=0;i<size;i++)
    {
        printf("%d\n", arr[i]);
    }
}

python代码

from ctypes import *

lib=CDLL("test")
# 传递数组
arr=[1,2,3,4,5,6]
# 转换数组类型
arrType=c_int*len(arr)
# *将list中每一个元素当做位置参数,等同于 tenArrType(1,2,3,...)
carr=arrType(*arr)
# (arrType,) 中的逗号是让python解析是一个元组
lib.testArray.argtypes=(arrType,)
lib.testArray(carr,len(arr))

返回值函数

C语言代码

//返回整型
LIB int returnInt() 
{
    return 100;
}
//返回普通字符串
LIB  char * returnStr() 
{
    static char str[] = "returnStr";
    return str;
} 

//返回宽字符
LIB  wchar_t * returnWStr()
{
    static wchar_t str[] = L"returnWStr";
    return str;
}

python代码

lib=CDLL("test")
# 返回整型
re=lib.returnInt();
print("returnInt=",re)

#返回 普通字符串
lib.returnStr.restype=c_char_p
re=lib.returnStr()
print("returnStr=",re)

#返回宽字符
lib.returnWStr.restype=c_wchar_p
re=lib.returnWStr()
print("returnWStr=",re)

传递指针和返回指针

C语言代码

//传递指针并且返回指针
LIB int* testPointer(float *fp) 
{
    //修改传递的指针
    *fp = 78.6f;
    static int re = 1001;
    //返回指针
    return &re;
}

python代码

from ctypes import *

lib=CDLL("test")
# 形参类型 要传递元组 POINTER返回指针类型
# (POINTER(c_float),) 中逗号是用来表示元组,切记一定加上
lib.testPointer.argtypes=(POINTER(c_float),)
#返回值类型
lib.testPointer.restype=POINTER(c_int)
#定义参数
testf1=c_float(8.5)
# byref(testf1) 将指针传递进去
re=lib.testPointer(byref(testf1))
#打印修改后的指针
print("input testf1=",testf1)
#获取指针的值 .contents.value
print("return=",re.contents.value)
print("return=",type(re))

回调函数

C语言代码

//定义回调函数
typedef void(*Callback)(int a);

//
LIB void testCallback(int *arr,int size,Callback call)
{
    for (int i = 0; i < size; i++) 
    {
        printf("%d \n", arr[i]);
    }

    //调用回调函数
    call(200);
}

python代码

from ctypes import *

lib=CDLL("test")

# 回调函数类型
# CFUNCTYPE(返回值,传递类型....)
FUNT=CFUNCTYPE(None,c_int)

#声明回调函数
def callback(a):
    print(a,end="\n")
    pass

#设置数组
arr=[1,2,3,4]
ArrType=c_int*len(arr)
carr=ArrType(*arr)

# 设置入参类型
lib.testCallback.argtypes=(ArrType,c_int,FUNT)
# 调用c语言函数
lib.testCallback(carr,c_int(len(arr)),FUNT(callback))

传递结构体

C语言代码

/*
  pos1 普通结构体
  pos2 指针结构体
  posArr3 数组结构体
*/
LIB Position * testStruct(Position pos1, Position* pos2, Position* posArr3, int size)
{
    printf("pos1=%d,%d \n", pos1.x, pos1.y);
    printf("pos2=%d,%d \n", pos2->x, pos2->y);
    for (int i = 0; i < size; i++) 
    {
        printf("posArr3=[%d,%d] \t", posArr3[i].x, posArr3[i].y);
    }

    //返回指针,这里加的static是因为 p1是局部变量,返回后c语言自动清除掉对象。static设置全局变量
    static struct Position p1;
    p1.x = 43;
    p1.y = 200;
    return &p1;
}

python代码

from ctypes import *

# 定义结构体
class Position(Structure):
    _fields_=[("x",c_int),("y",c_int)]
    pass

lib=CDLL("test")

# 传递普通结构体
pos1=Position(11,22)

# 传递指针结构体
pos2=Position(2,2)

# 传递数组结构体
pos3Arra=[Position(2,3),Position(4,3)]
arrType=Position*len(pos3Arra)
carr=arrType(*pos3Arra)

# 设置入参类型,1 普通结构体 2指针结构体 3 数组结构体 4数组长度
lib.testStruct.argtypes=(Position,POINTER(Position),arrType,c_int)
# 设置返回类型
lib.testStruct.restype=POINTER(Position)
re=lib.testStruct(pos1,byref(pos2),carr,len(pos3Arra))
# 获取返回值
print("\n")
print(re.contents.x,re.contents.y,sep="\t")

跨平台调用C语言动态库

from ctypes import *
from platform import system

sys=system()

if sys == "Windows":
    lib = CDLL("test")
elif sys == "Linux":
    lib = CDLL("test.so")
elif sys == "Darwin": # macos
    lib = CDLL("test.lib")
else:
    print(" unkon system ")

lib.print(b"hello world")

调用win32函数

from ctypes import  *

#API函数 参考https://blog.csdn.net/wang13342322203/article/details/81280377
# 调用win32 提示框
re=windll.user32.MessageBoxA(0,"我是一个窗口".encode("gbk"),"系统提示".encode("gbk"),1) #0普通窗口 ,1确认窗口
if(re==1):
    windll.user32.MessageBoxW(0,"点击了确认按钮","系统提示",0)
else:
    windll.user32.MessageBoxW(0,"点击了取消按钮","系统提示",0)
上一篇 下一篇

猜你喜欢

热点阅读