2012-11-05 5 views
3

파이썬 프로그램의 C 확장에서 전역 변수로 두 개의 입력을 주 C 함수 (수백만 번 호출)로 설정하여 성능을 향상 시키려고합니다. 그들은 자주 변경되지 않으므로, C 함수 (딱딱하지 않은 시간 낭비)에 람다 래퍼 (lambda wrapper)를 사용하여 파이썬에서 계속 제공 할 필요가 없습니다. 내 코드는 다음과 같습니다. 그런 다음C 파이썬 확장의 전역 PyObject * 변수

unsigned char* splitArray; 
PyObject* wordCmp; 

들을 설정하는 파이썬 API 기능 : 우선은 파일의 상단에있는 전역 변수를 선언 splitArray는 128 문자 배열에 할당이 경우

static PyObject* py_set_globals(PyObject *self, PyObject *args) 
{ 
    free(wordCmp); 
    free(splitArray); 

    char* splitChars; 
    PyObject* wordC; 

    if (!PyArg_ParseTuple(args, "sO", &splitChars, &wordC)) 
     return NULL; 

    wordCmp = (PyObject*)malloc(sizeof(PyObject)); 
    memcpy(wordCmp, wordC, sizeof(PyObject)); 
    splitArray = splitchars_to_mapping(splitChars); 

    return Py_BuildValue(""); 
} 

을하는 splitchars_to_mapping 함수에서 malloc 될 것입니다. 그리고 wordCmp는 C로 전달되는 파이썬 함수 객체입니다. 어쨌든, 내가 말할 수있는 한, char * splitArray는 전역 변수로 잘 작동하지만 나중에 wordCmp를 호출하려고 할 때 PyEval_CallObject를 사용하면 Python/C가 충돌합니다. 그래서 두 가지 질문이 있습니다

  1. 않는 이유는 바로 내가 함수의 시작 부분에서 초기화되지 않은 포인터 wordCmp 및 splitArray을 확보하려고하지 않을 때 C 충돌?
  2. 힙에 제대로 저장하고 글로벌 참조로 저장할 때 나중에 wordCmp를 호출 할 수없는 이유는 무엇입니까? 초기화되지 않은 전역 변수를 free'ing 때 충돌하지 않는 이유 첫 번째 질문,에 관해서는

답변

3

, 즉 글로벌 (정적) 변수는 프로그램이로드 될 때 zero 초기화 (guaranteed by the standard) 당신이 호출 할 때되기 때문이다 free()NULL (또는 0) 아무 것도 수행하지 않습니다. 사람 free(1)에서

:

free (ptr)가 전에 이미 호출 된이 정의되지 않은 문제가 발생합니다. ptr이 NULL이면 아무 작업도 수행되지 않습니다.

편집 : 두 번째 질문은 당신이 PyObject을 복사하려는 당신이하지 말아야한다는 사실에 관련되어, 그 PyObject 구조는 포인터를 포함 할 수 있으며 을 할 수 deep 복사는 해당 구조에 대한 액세스 권한이 없기 때문에 참조 횟수를 늘리고 이후 사용을 위해 참조를 유지해야합니다. O을 사용할 때 참조 수가 이 아닌이 증가한 docs :

O (객체) [PyObject *] C 객체 포인터에 파이썬 객체를 (변환없이) 저장하십시오. 따라서 C 프로그램은 이 통과 한 실제 객체를받습니다. 개체의 참조 횟수가 증가하지 않습니다.

그래서 당신은 참조 스스로를 증가한다, 그이 example

static PyObject *my_callback = NULL; 

static PyObject* my_set_callback(PyObject *dummy, PyObject *args) 
{ 
    PyObject *result = NULL;  
    if (PyArg_ParseTuple(args, "O:set_callback", &my_callback)) { 
     if (!PyCallable_Check(my_callback)) { 
      PyErr_SetString(PyExc_TypeError, "parameter must be callable"); 
      return NULL; 
     } 
     Py_XINCREF(my_callback); /* Add a reference to new callback */   
     Py_INCREF(Py_None);  /* Boilerplate to return "None" */ 
     result = Py_None; 
    } 
    return result; 
} 
+0

좋아요, 감사를 참조하십시오. 그래서 내 선언은 "unsigned char * splitArray = NULL; PyObject * wordCmp = NULL;"와 동일합니다. – dpitch40

+0

@ dpitch40 예 표준에 의해 보증됩니다.이 대답 참조 http://stackoverflow.com/a/6212973/1157444 – iabdalkader

+0

@ dpitch40 업데이트 된 답변 확인 – iabdalkader