2012-04-21 3 views
7

파이썬 C 확장을 사용하기 시작한 이유는 파이썬에서 호출 할 수있는 C 함수가 2 개의 PyObject * 인수 PyObject *를 반환합니다. 나는 다음에 "Hello World"확장자를 썼다 :파이썬 C 확장 기능 - 호출 가능한 C 함수가 인수를 가져와 PyObject를 반환해야하는 이유 *

#include <Python.h> 

static PyObject * 
hello_world(PyObject *self, PyObject *noargs) 
{ 
    printf("Hello World\n"); 
    return Py_BuildValue(""); 
} 


// Module functions table. 

static PyMethodDef 
module_functions[] = { 
    { "hello_world", hello_world, METH_NOARGS, "hello world method" }, 
    { NULL } 
}; 


// This function is called to initialize the module. 
PyMODINIT_FUNC 
inittesty2(void) 
{ 
    Py_InitModule("testy2", module_functions); 
} 

수없는 이유는 I (특히 METH_NOARGS와) 다음 그래서 hello_world 방법을 사용

static void 
hello_world() 
{ 
    printf("Hello World\n"); 
} 

를?

답변

10

다양한 PyObject 포인터에 대해 여러 가지 사항이 있습니다.

  1. 반환형로 필요한 하나

    예외 처리기구에 사용된다. 특히 함수가 널 포인터를 반환하면 파이썬 인터프리터는 예외를 throw합니다. (당신은 단지 PyErr_.. 기능 중 하나를 호출 한 후 특정 예외를 설정하는 것을해야한다.) 이것은 또한 당신이 예외를 throw하지 않으려 할 때마다, 당신은 진짜 PyObject에 대한 포인터를 반환해야한다는 것을 의미

    . 함수가 반환해야하는 것이 아무것도없는 경우 Py_None (Py_RETURN_NONE 매크로를 사용하는 것이 가장 좋으며 참조 횟수를 얻기 위해 사용하는 것이 가장 좋습니다) 또는 "true"(Py_RETURN_TRUE 사용)를 반환하면됩니다.

  2. 인자의 함수, 또는이 속한 모듈 인스턴스에서 호출되는 객체 PyObject *self 포인트. 정의하는 모든 함수는 클래스 메서드 또는 모듈 메서드입니다. 완전히 독립적 인 기능은 없습니다.

  3. 인수 (튜플 또는 다중 인수 목록 일 수있다) 함수 인수 PyObject *args 포인트. 당신은 어떤 인수를 취하지 않는 함수가 —을 필요로하지 않아야한다는 것을 지적하는 것이 옳다. 내가 말할 수있는 한, 당신이 옳다.당신은 그것을 정의 할 필요가 없다. 데이터가 사용자가 정의한 입력을 위해 당신이 PyMethodDef에 넣어 때 당신은 단순히 당신은 여전히 ​​PyCFunction캐스팅이해야합니다

    static PyObject *PyMyClass_MyFunc(PyObject *self) { 
        /* ..do something.. */ 
        Py_RETURN_TRUE; 
    } 
    

    등의 기능을 정의 할 수 있습니다,하지만 난 캐스트 당신만큼 안전하다고 생각 METH_NOARGS 플래그를 사용하십시오. 그러나 가능한 위험에 대해서는 아래 설명에 유의하십시오.

    static PyObject *PyMyClass_Func(PyObject *self, PyObject *args, PyObject *kwds) 
    { 
        /*...*/ 
    } 
    

    세 번째 인수는 이름 에 사용되는 선택적 인수 :

  4. 마지막으로, 기능은 사실 이런 세 번째 인수가있을 수 있습니다. 이 경우도 PyCFunction으로 함수 포인터를 캐스팅해야하지만 메서드 테이블에 함수에 맞는 플래그 (METH_KEYWORDS)를 설정하면 해당 포인터도 안전합니다.

+0

'PyNone'이 아니라'Py_None'입니다. 또한'Py_RETURN_TRUE' 및'Py_RETURN_FALSE'와 비슷한'Py_RETURN_NONE'도 있습니다. – yak

+0

(3) 들어, 만약 내가 틀렸어하지만 코드가 모든 args가 스택에 전달되고 호출 수신자 (함수)가 스택에서 팝하는 호출 규칙을 사용했다면 사용하지 않는 인수를 제거하면 충돌은 파이썬이 항상 두 번째 인자로 NULL을 전달할 것이고 함수는 그것을 팝하지 않기 때문입니다. – yak

+0

@yak 코드에 크래시가 발생하지 않습니다. – jogojapan

2

파이썬 함수는 방금 표준 출력으로 인쇄하는 사소한 함수이기 때문에 C 함수를 감싸는 래퍼 이상입니다.

가장 간단한 경우, 파이썬의 내부 기능에 대해 생각해보십시오.

>>> def hello(): 
...  print 'hello' 
... 
>>> dir(hello) 
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name'] 

당신은 물론 단지 C 함수를 감싸 확장 기능을 상상할 수 : 파이썬 기능을 사용하면 조회 할 수 있습니다 전체 자란 개체입니다. SWIG을 확인하십시오. 그러면 Python을 비롯한 많은 스크립팅 언어에 대한 쓰기 확장이 가능합니다. 가장 낮은 공통 분모가 될 것이므로, hello_world과 같은 함수를 래핑 할 수는 있지만, 당연히 많은 권력을 잃을 수도 있습니다.

4

모듈 수준 함수의 첫 번째 인수는 모듈 개체입니다. C에서 클래스를 정의 할 때 (동일한 PyMethodDef 구조체가이 메소드에 사용됨) 첫 번째 인수는 인스턴스입니다 (Python에서는 self과 유사 함).

METH_NOARGS을 사용하는 경우 Python은 NULL을 두 번째 인수로 전달합니다. 그들은 하나의 인수로 함수에 캐스트 할 수 있지만 필요 없다고 생각합니다.

반환 값은 설명하기 쉽습니다. 모든 파이썬 함수에는 반환 값이 있습니다. 파이썬에서 return을 명시 적으로 사용하지 않으면이 함수는 None을 반환합니다.

물론 C에서는 반환 값에 대해 명시해야하므로 사용하지 않으면 None을 반환해야합니다.

Py_RETURN_NONE; 

가 또는 전역 None 인스턴스를 직접 액세스 할 수 있습니다 :

Py_INCREF(Py_None); 
return Py_None; 

을하지만 매크로 사용하기 쉽게 파이썬이에 대한 매크로를 제공합니다.

NULL을 반환하면 None과 같아야하지만 NULL은 해당 함수가 예외를 발생 시켰음을 나타내는 데 사용할 수 있습니다.