【问题标题】:How to get value of char pointer from Python code wtih ctypes如何使用 ctypes 从 Python 代码中获取 char 指针的值
【发布时间】:2019-01-28 18:05:33
【问题描述】:

我想在 Python 上使用 C 库。 然后,我想从 C 库 fanction 中获取消息( char* )。

我编写了这些代码。 我得到了 result value(double* result_out) ,但没有收到消息。 此代码显示“c_char_p(None)”。

有什么想法吗?

我使用 Python 3.6 和 Ubuntu Bash。

C (libdiv.so):

#define ERROR -1
#define OK     0

int div (double x, double y, char *msg, double *result_out) {
    static char *err_msg = "0 div error"; 
    if(y == 0) {
        msg = err_msg;
        return ERROR;
    }
    *result_out = x/y;
    return OK;
}

Python:

from ctypes import *

lib = cdll.Loadlibrary('libdiv.so')
errmsg = c_char_p()
result = c_double(0)
rtn = lib.div(10, 0, errmsg, byref(result))

if rtn < 0:
    print (errmsg)       # None    
else :
    print (result.value) # OK.

【问题讨论】:

    标签: python c ctypes


    【解决方案1】:

    要将值作为输出参数返回,您需要传递一个指向返回值类型的指针。就像您使用double* 来接收双倍一样,您需要char** 来接收char*

    #ifdef _WIN32
    #   define API __declspec(dllexport)
    #else
    #   define API
    #endif
    
    #define OK     0
    #define ERROR -1
    
    API int div(double x, double y, char** ppMsg, double* pOut)
    {
        static char* err_msg = "0 div error";
        if(y == 0)
        {
            *ppMsg = err_msg;
            return ERROR;
        }
        *pOut = x / y;
        return OK;
    }
    

    在 Python 中,您还需要声明参数类型,否则默认情况下 Python 会将值编组为 C 为 c_int,这将破坏 double 并可能破坏 char*,具体取决于指针实现你的操作系统:

    from ctypes import *
    
    lib = CDLL('test')
    lib.div.argtypes = c_double,c_double,POINTER(c_char_p),POINTER(c_double)
    lib.div.restype  = c_int
    
    errmsg = c_char_p()
    result = c_double()
    rtn = lib.div(10, 0, byref(errmsg), byref(result))
    
    if rtn < 0:
        print(errmsg.value)
    else:
        print(result.value)
    

    输出:

    b'0 div error'
    

    【讨论】:

    • 感谢您的精彩代码!我得到了通过 **char 所需的东西。
    【解决方案2】:

    这里的主要问题是你的 C 被破坏了。为 msg 参数赋值不会在调用者端做任何可见的事情(就像你试图在 Python 函数中为参数赋值一样)。

    如果您想让div 的调用者真正使用错误消息字符串,您需要采用char**,而不是char*,并分配给*msg。在 Python 端,你会传递类似 byref(errmsg) 的东西。

    除此之外,您需要在lib.div 上设置argtypesrestype,否则Python 将不知道如何正确传递参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-28
      相关资源
      最近更新 更多