[英]How to pass a string pointer-to-pointer from C to Python?
I need to pass a string pointer-to-pointer from C to Python, so Python can update the pointer and C can read it later.我需要将一个字符串指针从 C 传递到 Python,这样 Python 可以更新指针,C 可以稍后读取它。
Steps脚步
char**
char**
char**
char**
C Code: C 代码:
#include <stdio.h>
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
typedef void (*CALLBACK)(char**);
CALLBACK g_cb;
// Expose API to register the callback
API void set_callback(CALLBACK cb) {
g_cb = cb;
}
// Expose API to call the Python callback with a char**
API void call_python_function(char** pp) {
if(g_cb) {
g_cb(pp);
printf("Python response: %s\n", *pp);
}
}
Python Code: Python 代码:
import ctypes as ct
CALLBACK = ct.CFUNCTYPE(None, PPCHAR)
dll = ct.CDLL('./test')
dll.set_callback.argtypes = CALLBACK,
dll.set_callback.restype = None
dll.call_python_function.argtypes = POINTER(POINTER(ctypes.c_char)),
dll.call_python_function.restype = None
dll.set_callback(my_function)
def my_function(pp):
buffer = ct.create_string_buffer(128)
pp = buffer
Output: Output:
Python response: (null)
No errors or warnings while building, C can call the Python function no issue, but Python can't update the char**
.构建时没有错误或警告,C 可以调用 Python function 没问题,但 Python 无法更新
char**
。 My question is How can I pass a string pointer-to-pointer from C to Python?我的问题是如何将字符串指针从 C 传递到 Python?
Here's a working example of passing a char**
from C to Python.这是将
char**
从 C 传递到 Python 的工作示例。
test.c测试.c
#include <stdio.h>
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
typedef void (*CALLBACK)(char**);
CALLBACK g_cb;
// Expose API to register the callback
API void set_callback(CALLBACK cb) {
g_cb = cb;
}
// Expose API to call the Python callback with a char**
API void call_python_function(char** pp) {
if(g_cb) {
g_cb(pp);
printf("%s\n", *pp);
}
}
test.py测试.py
import ctypes as ct
# Set up some types.
# Note that `c_char_p` can't be used as ctypes has special handling
# to convert it to a Python bytes object that inteferes with the
# callback working properly.
PCHAR = ct.POINTER(ct.c_char)
PPCHAR = ct.POINTER(PCHAR)
CALLBACK = ct.CFUNCTYPE(None, PPCHAR) # Note first parameter is return value
dll = ct.CDLL('./test')
# Declare function arguments and return values
dll.set_callback.argtypes = CALLBACK,
dll.set_callback.restype = None
dll.call_python_function.argtypes = PPCHAR,
dll.call_python_function.restype = None
# Set up callback function. Note that the buffer can't go out-of-scope
# once the function returns or undefined behavior occurs, so the buffer
# is stored as an attribute of the function object so it will continue
# to exist. A global variable would work, too.
@CALLBACK
def my_function(pp):
my_function.buffer = ct.create_string_buffer(b'Hi From Python')
pp[0] = my_function.buffer # [0] dereferences char** so can assign char*
dll.set_callback(my_function)
p = PCHAR()
dll.call_python_function(ct.byref(p))
# Cast to a `c_char_p` to access `.value` and get a bytes object
# up to the terminating null.
print(ct.cast(p, ct.c_char_p).value)
Output: Output:
Hi From Python
b'Hi From Python'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.