在Python中使用回调时出错

Ale*_* VI 10 c++ python error-handling callback char

我正在开发一个应该在Python中使用的DLL.我有一个回调函数来发送我的参数(在一个单独的标题中定义):

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;

}
Run Code Online (Sandbox Code Playgroud)

我以这种方式导出它:

__declspec(dllexport) int ResultCallback(call_nBest theList){
    nBestList = theList;
    return(0);
}
Run Code Online (Sandbox Code Playgroud)

我以这种方式首先在另一个C++应用程序中测试了我的回调:

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);
}
Run Code Online (Sandbox Code Playgroud)

main()我给这样的回调:

ResultCallback(MyCallback);
Run Code Online (Sandbox Code Playgroud)

它运作得很好.但我不知道如何适应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
Run Code Online (Sandbox Code Playgroud)

错误

现在我有这个错误:

未处理的异常: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
OS版本:6.3.9600.2.0.0.256.4
区域设置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
Run Code Online (Sandbox Code Playgroud)

所有工作都没有错误,我可以在控制台中看到这个(在这种情况下nB10):

0
1
...
9
Run Code Online (Sandbox Code Playgroud)

其次,我改变了这个功能:

def callbackU(OutList,ConList,nB):
    for i in range(nB):
        print (cast(OutList,c_char_p))
return 0
Run Code Online (Sandbox Code Playgroud)

哦,哦,这只打印列表中的第一个单词(nB次)

nel*_*fin 3

你想要这样的东西吗?

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

据我了解,您只是想将 Python 函数的输出callbackU与 C++MyCallback函数相匹配。

Python 具有多种字符串格式化功能,乍一看可能会令人困惑,但它向printf字符串格式化致敬。

由于OutList具有类型LP_LP_c_char(指向 的指针c_char,与“NULL终止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
Run Code Online (Sandbox Code Playgroud)