Подтвердить что ты не робот

Ошибка использования обратного вызова в Python

Я разрабатываю dll, который должен использоваться в Python. У меня есть функция обратного вызова для отправки моих параметров (определенных в отдельном заголовке):

typedef int(*call_nBest)(char **OutList, float* confList, int nB);

Итак, я использую этот обратный вызов следующим образом:

#define TEXT_BUFFER_MAX_SIZE 50
call_nBest nBestList;
void Xfunction(const char* aLineThatWillBeConvertedInAList){
    char **results;
    float *confidences;
    confidences=new float[nBest];
    results=new char*[nBest];
    for(int i=0; i<nBest; i++) results[i]=new char[TEXT_BUFFER_MAX_SIZE];

    MakeLine2List(aLineThatWillBeConvertedInAList,results,confidences); 

    /*At this function I am having the error :(*/
    nBestList(results,confidences,nBest); // Passing the values to my callback

    for(int i=0; i<nBest; i++) delete [] results[i];
    delete [] confidences;
    delete [] results;

}

И я экспортирую его таким образом:

__declspec(dllexport) int ResultCallback(call_nBest theList){
    nBestList = theList;
    return(0);
}

Я проверил свой обратный вызов сначала в другом приложении на С++ следующим образом:

int MyCallback(char **OutLi, float* confLi, int nB){
    printf("\n The nB results: %d \n",nB);
    for(int n=0; n<nB; n++){
        std::cout << *(confLi+n) << "\t" << OutLi[n] << "\n";
    }
    return(0);
}

В main() я вызываю обратный вызов следующим образом:

ResultCallback(MyCallback);

и он работает очень хорошо. Но я не знаю, как адаптировать это к Python. Я пробовал это:

Примечание: Я изменил последний способ, потому что я разрешил некоторые ошибки, но я все еще получаю сообщение об ошибке. Это текущий способ загрузки myDLL

from ctypes import *
def callbackU(OutList,ConList,nB):
    for i in range(nB):
        print(OutList[i][0:50]) #I don't know how to print the values
return 0

myDLL = cdll.LoadLibrary("MyLibrary.dll")

calling = CFUNCTYPE(c_int,POINTER(POINTER(c_char)),POINTER(c_float),c_int)
theCall= calling(callbackU)
myDLL.ResultCallback(theCall)

myDLL.StartProcess(); #In this process the given callback will be invoqued

ОШИБКА

И теперь у меня есть эта ошибка:

Необработанное исключение: System.AccessViolationException: Попытка чтение или запись защищенной памяти. Это часто свидетельствует о том, что другие память повреждена. при Xfunction (SByte * aLineThatWillBeConvertedInAList)

Подпись задачи:

Проблема Название события: APPCRASH
 Название приложения: python.exe
 Версия приложения: 0.0.0.0
 Временная метка приложения: 54f9ed12
 Имя модуля неисправности: MSVCR100.dll
 Версия модуля неисправности: 10.0.40219.325
 Временная метка: 10.0.40219.325
 Код исключения: c0000005
 Смещение смещения: 00001ed7
 Версия ОС: 6.3.9600.2.0.0.256.4
 Locale ID: 1033
 Дополнительная информация 1: 5861
 Дополнительная информация 2: 5861822e1919d7c014bbb064c64908b2
 Дополнительная информация 3: a10f
 Дополнительная информация 4: a10ff7d2bb2516fdc753f9c34fc3b069

Вещи, которые я сделал, и почти то, что я хочу:

Сначала я изменил функцию Python обратного вызова для этого:

def callbackU(OutList,ConList,nB):
    for i in range(nB):
        print(i)
return 0

Все работает без ошибок, и я вижу это в консоли (в этом случае nB был 10):

0
1
...
9

Во-вторых, я изменил функцию следующим образом:

def callbackU(OutList,ConList,nB):
    for i in range(nB):
        print (cast(OutList,c_char_p))
return 0

и, что удивляет, это печатает только первое слово списка (nB раз)

4b9b3361

Ответ 1

Вам нужно что-то вроде этого?

def callbackU(OutList, ConList, nB):
    for i in range(nB):
        print("{}\t{}".format(ConList[i], cast(OutList[i], c_char_p)))
    return 0

Из того, что я понимаю, вы просто пытаетесь сопоставить вывод своей функции Python callbackU со своей функцией С++ MyCallback.

Python имеет множество функций форматирования строк, которые могут сбивать с толку вначале, но отдает дань printf форматированию строк.

Так как OutList имеет тип LP_LP_c_char (указатель на указатель c_char, vs "NULL terminated char *" c_char_p), мы бы лучше превратили его в собственный тип данных Python, например:

def callbackU(OutList, ConList, nB):
    for i in range(nB):
        out_list_item = cast(OutList[i], c_char_p).value
        print("{}\t{}".format(ConList[i], out_list_item))
    return 0