如何使用 ctypes 从 Python 代码中获取 char 指针的值
How to get value of char pointer from Python code wtih ctypes
我想在 Python 上使用 C 库。
然后,我想从 C 库 fanction 获取消息 ( char* )。
我写了这些代码。
我得到了 result value(double* result_out) ,但我没有收到消息。
此代码显示 "c_char_p(None)".
有什么想法吗?
我用的是Python3.6,UbuntuBash。
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.
这里的主要问题是你的 C 坏了。为 msg
参数赋值不会在调用者端做任何可见的事情(就像你试图在 Python 函数中赋值给一个参数一样)。
如果您想让 div
的调用者实际使用错误消息字符串,您需要使用 char**
而不是 char*
,并分配给 *msg
。在 Python 端,您将传递类似 byref(errmsg)
.
的内容
除此之外,您需要在 lib.div
上设置 argtypes
和 restype
,否则 Python 将不知道如何正确传递参数。
要return一个值作为输出参数,需要传递一个指向returned值类型的指针。就像您使用 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*
,具体取决于 OS:
的指针实现
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'
我想在 Python 上使用 C 库。 然后,我想从 C 库 fanction 获取消息 ( char* )。
我写了这些代码。 我得到了 result value(double* result_out) ,但我没有收到消息。 此代码显示 "c_char_p(None)".
有什么想法吗?
我用的是Python3.6,UbuntuBash。
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.
这里的主要问题是你的 C 坏了。为 msg
参数赋值不会在调用者端做任何可见的事情(就像你试图在 Python 函数中赋值给一个参数一样)。
如果您想让 div
的调用者实际使用错误消息字符串,您需要使用 char**
而不是 char*
,并分配给 *msg
。在 Python 端,您将传递类似 byref(errmsg)
.
除此之外,您需要在 lib.div
上设置 argtypes
和 restype
,否则 Python 将不知道如何正确传递参数。
要return一个值作为输出参数,需要传递一个指向returned值类型的指针。就像您使用 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*
,具体取决于 OS:
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'