繁体   English   中英

当“ C”回调函数具有char **参数时,如何在Python中使用ctypes

[英]How to use ctypes in Python, when the “C” callback has param with char **

我正在尝试使用包含一个lib.so文件的python代码进行lib.so C语言有一个回调方法,要我将字符串放入给定地址。

我花了整整一个星期的时间来解决这个问题。...现在,我已经将字符串传递给C了。但是接下来的问题出现了……“ C”不能free()我的由python创建的字符串指针。

`/ usr / bin / python'中的错误:free():无效的指针

我省略了其他头代码

typedef struct
{
    int (*Info) (int resId,char **outbuff);
} OptFuncs;

这是C代码


OptFuncs g_sdk_opt_funcs = {NULL};


int SDK_INIT(OptFuncs *optfuncs)
{
    g_sdk_opt_funcs = *optfuncs;
    return 0;
}

int SDK_RUN()
{
    resId = 6604;
    char *szvalbuf = NULL;

    g_sdk_opt_funcs.Info(resId,&szvalbuf);

    if(szvalbuf) {free(szvalbuf); szvalbuf = NULL;}
    // I guess that's the problem.

    return 0;
}

这是使用C语言的示例:

int myInfo(int resId,char **outbuff)
{
    int iret = 0;
    *outbuff = NULL;

    char buff[512];
    int  buflen = sizeof(buff);
    memset(buff,0,sizeof(buff));

    if(resId == 6604)
    {
    snprintf(buff,buflen,"4GB");
    }

    if(iret == 0)
    {
        *outbuff = (char*)malloc(strlen(buff)+1);
        strcpy(*outbuff,buff);
    }

    return iret;
}

int main(int argc, char *argv[])
{
    OptFuncs optfuncs={NULL};
    optfuncs.Info = myInfo;

    int ret = SDK_INIT(&optfuncs);
    ret = SDK_RUN();
}

它适用于纯C。

而我的python函数是:


lib = CDLL('./lib/lib.so')

infoCallback = CFUNCTYPE(c_int, c_int, POINTER(POINTER(c_char)))

class OptFuncs(Structure):
    _fields_ = [("Info", infoCallback)]

def my_info(res_id, out_buff):
    iret = 0
    out_buff[0] = None
    if res_id == 6604:
        buff = '16GB'

    char_array = create_string_buffer(buff)
    out_buff[0] = cast(char_array, POINTER(c_char))
    return iret


optFuncs = OptFuncs()
optFuncs.Info = infoCallback(my_info)

# initialize the lib‘s callback.
lib.SDK_INIT.argtypes = [POINTER(OptFuncs)]
ret = lib.SDK_INIT(pointer(optFuncs))

# run the lib‘s main func.
ret = lib.SDK_RUN()

然后发生错误。

`/ usr / bin / python'中的错误:free():无效的指针

我做错了吗?

问题在于,内存是由Python的C运行时库中的create_string_buffer分配的,并在DLL的运行时库中释放的。 它们可能无法使用相同版本的编译器进行编译,而且我们内部也不知道create_string_buffer如何分配缓冲区。 DLL接收的指针可能不是分配的指针。 create_string_buffer可能会分配比您预期更多的存储ctypes元数据。 您不想释放由Python管理的内存。

要解决此问题,请确保在DLL中分配和释放数据。 例如,将此函数添加到DLL并调用它而不是create_string_buffer

C

API char* SDK_MALLOC(const char* buff)
{
    char* s = malloc(strlen(buff) + 1);
    strcpy(s,buff);
    return s;
}

蟒蛇

lib.SDK_MALLOC.argtypes = ()
lib.SDK_MALLOC.restype = POINTER(c_char)

my_info变为:

def my_info(res_id, out_buff):
    iret = 0
    out_buff[0] = None
    if res_id == 6604:
        buff = b'16GB'
    char_array = lib.SDK_MALLOC(buff)
    out_buff.contents = char_array
    return iret

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM