Roe*_*Roe 5 c python ctypes pointers
我正在尝试使用 cTypes 将字符串(作为指针)从 python 传递到 C 函数。
\n\nc 函数需要获取指向字符串(字符数组)的指针,但我还没有成功地让它与多个字符一起工作,但我唯一的成功(有点成功,看看输出)是使用 1 个字符和希望得到一些帮助!
\n\n我需要将字符串的指针发送到 char - (unsigned char * 输入)
\n\n我的Python代码:
\n\ndef printmeP(CHAR):\n print("In Print function")\n print(CHAR)\n c_sends = pointer(c_char_p(CHAR.encode(\'utf-8\')))\n print("c_sends: ")\n print(c_sends[0])\n python_p_printme(c_sends)\n print("DONE function - Python")\n print(c_sends[0])\n return\n\n\nfrom ctypes import c_double, c_int,c_char, c_wchar,c_char_p, c_wchar_p, pointer, POINTER,create_string_buffer, byref, CDLL\nimport sys\n\nlib_path = \'/root/mbedtls/programs/test/mylib_linux.so\' .format(sys.platform)\n\n\nCHAR = "d"\n\ntry:\n mylib_lib = CDLL(lib_path)\nexcept:\n print(\'STARTING...\' )\npython_p_printme = mylib_lib.printme\npython_p_printme.restype = None\nprintmeP(CHAR)\n\n\nRun Code Online (Sandbox Code Playgroud)\n\n我的C代码:
\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nvoid printme(char * param) {\n printf("\\nStart c Function!\\n");\n printf("%s\\n Printing param\\n ", param);\n char add = \'!\';\n strncat(param, &add, 1);\n\n printf("%s\\n Printing param\\n ", param);\n printf("Function Done - c\\n");\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我的输出:
\n\nIn Print function\nd <--- this is what i am sending\nc_sends: \nb\'d\' <--- this is after encoding\n\xef\xbf\xbd\xef\xbf\xbd[\xef\xbf\xbd <-------------=|\n Printing param |\n \xef\xbf\xbd\xef\xbf\xbd[\xef\xbf\xbd | This is the c code print\n Printing param | **Question:** Why does it print \'\xef\xbf\xbd\' and no what\'s supposed to be printed\n Function Done - c <--=|\nDONE function - Python\nb\'d!\' <--------------------- this is the last print that prints after the change.\n\nRun Code Online (Sandbox Code Playgroud)\n\n希望获得一些帮助,感谢所有参与的人:)
\n\n诚挚的,\n罗伊
\n存在很多问题:
.argtypes您的功能。它将捕获传递错误参数的错误。添加下面的行并注意它是复数并且是参数类型的元组。逗号构成 1 元组:python_p_printme.argtypes = c_char_p,
进行更改后,您将收到错误,因为此代码:
c_sends = pointer(c_char_p(CHAR.encode('utf-8')
实际上是发送一个C char**(指向c_char_p的指针)。正确设置 argtypes 后,您只需使用字节字符串调用该函数即可工作。你的函数变成:
def printmeP(CHAR):
print("In Print function")
print(CHAR)
python_p_printme(CHAR.encode())
print("DONE function - Python")
Run Code Online (Sandbox Code Playgroud)
create_unicode_buffer(for c_wchar_p) 或create_string_buffer(for c_char_p) 分配可变缓冲区;否则,strcatC 代码中的 将会损坏 Python 字符串。这是一个完整的示例:
测试.cpp
def printmeP(CHAR):
print("In Print function")
print(CHAR)
python_p_printme(CHAR.encode())
print("DONE function - Python")
Run Code Online (Sandbox Code Playgroud)
测试.py
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// For Windows compatibility
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
// For C++ compiler compatibility
#ifdef __cplusplus
extern "C" {
#endif
API void alter_me(char* param, size_t length) {
// truncates if additional info exceeds length
strncat_s(param, length, " adding some info", length - 1);
}
#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)
输出:
from ctypes import *
lib = CDLL('./test')
alter_me = lib.alter_me
alter_me.argtypes = c_char_p,c_size_t
alter_me.restype = None
data = create_string_buffer(b'test',size=10)
alter_me(data,sizeof(data))
print(data.value)
data = create_string_buffer(b'test',size=50)
alter_me(data,sizeof(data))
print(data.value)
Run Code Online (Sandbox Code Playgroud)
create_string_buffer请注意,如果 C 函数不更改缓冲区(例如 C 参数为 ),则不需要使用const char*。然后你就可以打电话了printme(b'test string')。
您可以使用create_string_buffer。
该文档可以在这里找到: https ://docs.python.org/3/library/ctypes.html#ctypes.create_string_buffer
ctypes.create_string_buffer(init_or_size, size=None)
该函数创建一个可变字符缓冲区。返回的对象是 c_char 的 ctypes 数组。
init_or_size 必须是指定数组大小的整数,或者是用于初始化数组项的字节对象。
您可以将buf.value.decode("utf-8")缓冲区转换回 UTF-8 python 字符串。
C 代码库的一个小示例可能如下所示:
from ctypes import *
mylib_lib = cdll.LoadLibrary("<your-lib>")
mylib_lib.printme.argtypes = c_char_p,
buf = create_string_buffer(128)
buf.value = b'Hello World'
mylib_lib.printme(buf)
print("print on python side:", buf.value.decode("utf-8"))
Run Code Online (Sandbox Code Playgroud)
它将输出:
Start c Function!
Hello World
...
print on python side: Hello World!
Run Code Online (Sandbox Code Playgroud)
在控制台上。