2014-06-24 2 views
0

python으로 C++ 라이브러리를 호출하려고합니다.ctype argtypes를 지정하는 이유

내 C++ 라이브러리 코드 :

#include <stdio.h> 

extern "C" { 

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

} 

내 파이썬 코드 :

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을 지정해야합니까?

답변

1

네가해야하는 이유는 그것이 ctypes 'guess 때문인 것입니다. int test_i(int i)int test_i(char i)으로 바꾸면 스택 손상이 발생합니다. 파이썬 측은 4 또는 8 바이트 기능을 제공하고 C 측은 1 바이트 만 읽으므로 스택 손상이 발생합니다. 플랫폼에 따라 약간의 시간 동안 주목을받지 못하거나 점차 스택을 먹거나 충돌이 발생하거나 아무 일도 일어나지 않을 것입니다. 어쨌든이 코드 스타일은 냄새가납니다.

ctypes은 파이썬 유형 시스템이 C보다 훨씬 간단하기 때문에 많은 경우 도움이되지 않습니다. 예를 들어, Python 측은 1 바이트, 2 바이트, 4 바이트 또는 8 바이트 정수를 전달하는지 알아낼 수있는 방법이 없습니다. 파이썬 정수는 크기가 없기 때문입니다. 파이썬에는 배정도 부동 소수점 만 있고 C면에는 단일 및 반수가 있으며 플랫폼 별 정밀도가있을 수 있습니다. 문자열과 바이트는 파이썬 측에서만 적절히 구분되며, C 측에서는 유니 코드로 작업하는 것이 일반적으로 엉망입니다. wchar_t[] 또는 char[]을 사용할 지 여부는 명확하지 않습니다. 문자열을 어떻게 종료 하시겠습니까?이 작업이 필요합니까, 그리고 어떻게 파이썬 문자열 불변성으로 돌아가고 싶습니까? argtypes이 없으면 구조와 배열을 쉽게 전달할 수 없습니다.

는 또한,도 restype를 지정하는 것을 잊지 마세요 : 기본적 ctypes으로

libc.test_f.restype = c_int 

는 모든 기능이 플랫폼에 대해 무엇이든, int을 반환 가정합니다. 호출 규칙에 따라 CPU 레지스터가 결과를 반환하는 데 사용할 수 있습니다.이 경우 레지스터가 읽혔는지 여부에 차이가 없으므로 해를 끼치 지 않습니다. 다른 경우 스택에 의해 결과가 전달되고 스택이 너무 많이 소모되면 스택 손상이 발생하지 않으므로 function RET은 잘못된 주소를 표시하고 SIGSEGV에 대한 인사를하는 것이 가장 좋습니다. 최악의 경우 해커는 애플리케이션을 사용하여 속임수를 쓰게됩니다.

일반적으로 argtypesrestype은 코드가 예측할 수없는 방식으로 분리되는 것을 방지하고 모든 것이 C와 Python에서 너무 많이 다르기 때문에 필요합니다. 그렇지 않다면 아무도 선 (Zen)과 배터리 (battery)로 인해 이들을 사용하도록 강요하지 않을 것입니다.

관련 문제