通过 Python 将空终止字符串发送到我的 C 代码
Sending null terminated string to my C code through Python
我正在向我的 BPF C 代码发送字符串,但我不确定传入的字符串是否以 null 结尾。如果不是,有没有办法让它们以空值终止?我将我的代码行发送到 BPF,这样我就可以使用我的 stringCounter 函数手动计算它们,但我一直不幸地陷入了一个永远的循环。这是我的 Python 代码的样子:
b = BPF(src_file="hello.c")
lookupTable = b["lookupTable"]
#add hello.csv to the lookupTable array
f = open("hello copy.csv","r")
contents = f.readlines()
for i in range(0,len(contents)):
string = contents[i].encode('utf-8')
lookupTable[ctypes.c_int(i)] = ctypes.create_string_buffer(string, len(string))
这是我为空终止字符串计数器找到的代码
int stringLength(char* txt)
{
int i=0,count=0;
while(txt[i++]!='[=12=]'){
count+=1;
}
return count;
}
ctypes.create_string_buffer(string, len(string))
不是零终止的。但是 ctypes.create_string_buffer(string)
是。很容易看出,因为 ctypes.create_string_buffer(string)[-1]
是 b'\x00'
,而 ctypes.create_string_buffer(string, len(string))
是 string
中的最后一个字节。
换句话说,如果你想要一个以零结尾的缓冲区,让 create_string_buffer
计算出长度。 (它使用来自 Python 字节对象的实际长度,因此如果您担心的话,它不会被内部 NUL 字节所愚弄。)
我不熟悉 BPF
但对于 ctypes
,如果您的字符串未被 C 代码修改,则您不需要 create_string_buffer
,因为它用于创建可变缓冲区,以及 Python Unicode 和字节字符串总是分别传递以 nul 结尾的 wchar_t*
或 char*
到 C 代码。假设您的函数在 test.dll
或 test.so
:
import ctypes as ct
dll = ct.CDLL('./test')
dll.stringLength.argtypes = ct.c_char_p,
dll.stringLength.restype = ct.c_int
print(dll.stringLength('somestring'.encode())) # If string is Unicode
print(dll.stringLength(b'someotherstring')) # If already a byte string
输出:
10
15
请注意,这并不排除在字符串本身中包含 nul,但在这种情况下,您的计数函数将 return 一个较短的值:
print(dll.stringLength(b'some[=12=]string')) # Output: 4
假设不要求 BPF
对象具有硬编码的 ctypes
类型作为索引和值,您的代码可能会写成以下形式。
with open("hello copy.csv") as file:
for i,line in enumerate(file):
lookupTable[i] = string.encode()
我正在向我的 BPF C 代码发送字符串,但我不确定传入的字符串是否以 null 结尾。如果不是,有没有办法让它们以空值终止?我将我的代码行发送到 BPF,这样我就可以使用我的 stringCounter 函数手动计算它们,但我一直不幸地陷入了一个永远的循环。这是我的 Python 代码的样子:
b = BPF(src_file="hello.c")
lookupTable = b["lookupTable"]
#add hello.csv to the lookupTable array
f = open("hello copy.csv","r")
contents = f.readlines()
for i in range(0,len(contents)):
string = contents[i].encode('utf-8')
lookupTable[ctypes.c_int(i)] = ctypes.create_string_buffer(string, len(string))
这是我为空终止字符串计数器找到的代码
int stringLength(char* txt)
{
int i=0,count=0;
while(txt[i++]!='[=12=]'){
count+=1;
}
return count;
}
ctypes.create_string_buffer(string, len(string))
不是零终止的。但是 ctypes.create_string_buffer(string)
是。很容易看出,因为 ctypes.create_string_buffer(string)[-1]
是 b'\x00'
,而 ctypes.create_string_buffer(string, len(string))
是 string
中的最后一个字节。
换句话说,如果你想要一个以零结尾的缓冲区,让 create_string_buffer
计算出长度。 (它使用来自 Python 字节对象的实际长度,因此如果您担心的话,它不会被内部 NUL 字节所愚弄。)
我不熟悉 BPF
但对于 ctypes
,如果您的字符串未被 C 代码修改,则您不需要 create_string_buffer
,因为它用于创建可变缓冲区,以及 Python Unicode 和字节字符串总是分别传递以 nul 结尾的 wchar_t*
或 char*
到 C 代码。假设您的函数在 test.dll
或 test.so
:
import ctypes as ct
dll = ct.CDLL('./test')
dll.stringLength.argtypes = ct.c_char_p,
dll.stringLength.restype = ct.c_int
print(dll.stringLength('somestring'.encode())) # If string is Unicode
print(dll.stringLength(b'someotherstring')) # If already a byte string
输出:
10
15
请注意,这并不排除在字符串本身中包含 nul,但在这种情况下,您的计数函数将 return 一个较短的值:
print(dll.stringLength(b'some[=12=]string')) # Output: 4
假设不要求 BPF
对象具有硬编码的 ctypes
类型作为索引和值,您的代码可能会写成以下形式。
with open("hello copy.csv") as file:
for i,line in enumerate(file):
lookupTable[i] = string.encode()