ctype为什么指定argtypes [英] ctype why specify argtypes

查看:449
本文介绍了ctype为什么指定argtypes的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用python调用c ++库。

I want to call c++ library with python.

我的C ++库代码:

#include <stdio.h>

extern "C" {

int test_i(int i)
{
    return i+1;
}

}

我的python代码:

My python code:

from ctypes import *
libc = cdll.LoadLibrary("cpp/libtest.so")
libc.test_f.argtypes = [c_int] # still works when comment
print libc.test_i(1)

我的问题是:如果我没有指定argtypes,它仍然可以工作!调用C / C ++函数时是否必须指定 argtypes

My question is: if I did not specify the argtypes, it is still work! Must I specify the argtypes when calling C/C++ function?

推荐答案

是的,您应该这样做,因为它起作用的原因是因为ctypes的猜测。将 int test_i(int i)替换为 int test_i(char i),您将得到堆栈损坏—因为Python端提供功能4或8个字节,而C端仅读取1个字节。视平台而定,这可能会在一段时间内被忽略,或者逐渐耗尽您的堆栈,或者立即崩溃,或者什么都不会发生-无论如何,这种代码样式都会闻起来。

Yes, you should, because why it had worked is because of ctypes' guess. Replace int test_i(int i) with int test_i(char i), and you will get stack corruption — because Python side gives function 4 or 8 bytes, while C side only reads 1 byte. Depending on platform, this may go unnoticed for some time, or gradually eat up your stack, or crash immediately, or nothing will happen — anyway, this code style smells.

ctypes 进行基本的类型转换,但在很多情况下都无济于事,因为Python类型系统比C语言简单得多。例如,Python端无法确定您要传递的是1字节,2字节,4字节还是8字节的整数,因为Python整数没有大小。 Python仅具有双精度浮点数,而C端也具有单精度和半精度,并且可能还具有特定于平台的精度。字符串和字节仅在Python端适当地分开,而在C端使用Unicode通常是一团糟。不清楚您要使用 wchar_t [] 还是 char [] ,您想如何终止字符串,您是否完全需要它,以及如何解决Python字符串不可变性。没有正确的 argtypes ,您将无法轻松传递结构和数组。

ctypes does basic type conversion, but it won't help in lots of cases, because Python type system is much simpler than C's. For example, Python side has no way to figure out if you're passing 1 byte, 2 bytes, 4 bytes or 8 bytes integer, because Python integers have no size. Python has only double precision floats, while C side has also single and half, and may have also platform-specific precisions. Strings and bytes are properly separated on Python side only, while on C side working with Unicode is generally a mess. It's not clear whether you want to use wchar_t[] or char[], how would you like to terminate your strings, and do you need this at all, and how do you want to go around Python string immutability. Without proper argtypes you can't pass in structures and arrays easily.

此外,也不要忘记指定 restype

Moreover, don't also forget to specify restype:

libc.test_f.restype = c_int

默认情况下 ctypes 假定所有函数都返回 int ,无论您的平台是什么。根据调用约定,有可能将CPU寄存器用于返回结果-在这种情况下,您不会受到伤害,因为无论是否读取寄存器都没有区别。在其他情况下,结果是通过堆栈传递的,这很麻烦,因为未使用足够的堆栈(以及过度使用)会导致堆栈损坏,因此函数的 RET 会弹出错误的地址,并且在最好的情况下向SIGSEGV问好。在最坏的情况下,黑客会使用您的应用程序进行欺骗。

By default ctypes assumes all functions return int, whatever it is for your platform. Depending on calling convention it's possible that CPU register will be used for returning result — in this case you won't be harmed, because it makes no difference whether register was read or not. In other case result is passed by stack, and you are screwed, because not consuming enough stack (as well as overconsuming) leads to stack corruption, function's RET will pop wrong address and say hello to SIGSEGV in best case. In worst, hackers will be doing trickery using your application.

通常, argtypes restype 是您的朋友,因为它们可以防止您的代码以不可预测的方式瓦解,并且之所以需要它们,仅仅是因为C和Python中的所有内容都太大了。如果不是这样的话,由于Zen和电池的存在,没有人会简单地强迫您使用这些。

Generally, argtypes and restype are your friends, because they protect your code from falling apart in unpredictable ways, and they are needed just because everything is way too much different in C and Python. If it wasn't, nobody would simply force you to use these ever, because of Zen and batteries.

这篇关于ctype为什么指定argtypes的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆