Python ctypes 正在写入要由 C 可执行文件读取的数据
Python ctypes writing data to be read by C executable
我正在尝试学习如何使用 Python ctypes 库将数据写入 C 可执行文件可以轻松读取的文件。在我整理的小测试用例中,我 运行 遇到了 reading/writing 字符数组的一些问题。
目前,我有三个源文件。 write_struct.py
用两个创建一个简单的结构
条目,一个名为 git
的整数值和一个名为 command
的字符数组,然后使用 ctypes.fwrite
将结构写入文件。 read_struct.c
和 read_struct.h
编译成一个可执行文件,该可执行文件在内部定义了与 write_struct.py
中的结构相同的结构,然后读入由 python 脚本写入的数据并将其打印出来。
目前,python 文件中分配了以下值(并非字面上所示的方式,向下滚动以查看实际代码):
git = 1
command = 'cp file1 file2'
并且当 运行 时,C 可执行文件打印以下内容:
git: 1
command:
我意识到问题几乎可以肯定是 command
变量在 python 脚本中的分配方式。我读过 c_char_p()
(我目前用来初始化该变量中的数据的函数)不会创建指向可变内存的指针,应该使用 create_string_buffer()
,但我不是确定这是如何将数据添加到结构或将其写入文件的。我想我也对将 pointers/their 数据写入文件一开始的工作方式感到困惑。执行此操作的最佳方法是什么?
提前感谢任何能够提供帮助的人!!
我的三个文件的代码如下,供参考:
write_struct.py
:
"""
write_struct.py
"""
from ctypes import *
libc = cdll.LoadLibrary("libc.so.6")
class DataStruct(Structure):
_fields_ = [("git", c_int),
("command", c_char_p)
]
def main():
pydata = DataStruct(1, c_char_p("cp file1 file2"))
libc.fopen.argtypes = c_char_p, c_char_p
libc.fopen.restype = c_void_p
libc.fwrite = libc.fwrite
libc.fwrite.argtypes = c_void_p, c_size_t, c_size_t, c_void_p
libc.fwrite.restype = c_size_t
libc.fclose = libc.fclose
libc.fclose.argtypes = c_void_p,
libc.fclose.restype = c_int
f = libc.fopen("stored_data", "wb")
libc.fwrite(byref(pydata), sizeof(pydata), 1, f)
libc.fclose(f)
return 0
main()
read_struct.c
:
/*
* read_struct.c
*
*/
#include "read_struct.h"
int main()
{
data_struct cdata = malloc(DATASIZE);
FILE *fp;
if ((fp = fopen("stored_data", "r")) != NULL) {
fread(cdata, DATASIZE, 1, fp);
printf("git: %i\n", cdata->git);
printf("command:");
printf("%s\n", cdata->command);
fclose(fp);
} else {
printf("Could not open file\n");
exit(1);
}
return 0;
}
read_struct.h
:
/*
* read_struct.h
*
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct _data_struct *data_struct;
struct _data_struct {
int git;
char command[40];
};
#define DATASIZE sizeof(struct _data_struct)
可以直接用Python写入二进制数据。 ctypes
可用于创建结构并支持位字段和联合,或者对于简单结构,可以使用 struct
模块。
from ctypes import *
class DataStruct(Structure):
_fields_ = [("git", c_int),
("command", c_char * 40)] # You want array here, not pointer
pydata = DataStruct(1,b'cp file1 file2') # byte string for initialization.
with open('stored_data','wb') as f: # write file in binary mode
f.write(pydata) # ctypes support conversion to bytes
import struct
# See struct docs for formatting codes
# i = int (native-endian. Use <i to force little-endian, >i for big-endian)
# 40s = char[40] (zero-padded if initializer is shorter)
pydata = struct.pack('i40s',1,b'cp file1 file2')
with open('stored_data2','wb') as f:
f.write(pydata)
参考:https://docs.python.org/3/library/struct.html#format-strings
我正在尝试学习如何使用 Python ctypes 库将数据写入 C 可执行文件可以轻松读取的文件。在我整理的小测试用例中,我 运行 遇到了 reading/writing 字符数组的一些问题。
目前,我有三个源文件。 write_struct.py
用两个创建一个简单的结构
条目,一个名为 git
的整数值和一个名为 command
的字符数组,然后使用 ctypes.fwrite
将结构写入文件。 read_struct.c
和 read_struct.h
编译成一个可执行文件,该可执行文件在内部定义了与 write_struct.py
中的结构相同的结构,然后读入由 python 脚本写入的数据并将其打印出来。
目前,python 文件中分配了以下值(并非字面上所示的方式,向下滚动以查看实际代码):
git = 1
command = 'cp file1 file2'
并且当 运行 时,C 可执行文件打印以下内容:
git: 1
command:
我意识到问题几乎可以肯定是 command
变量在 python 脚本中的分配方式。我读过 c_char_p()
(我目前用来初始化该变量中的数据的函数)不会创建指向可变内存的指针,应该使用 create_string_buffer()
,但我不是确定这是如何将数据添加到结构或将其写入文件的。我想我也对将 pointers/their 数据写入文件一开始的工作方式感到困惑。执行此操作的最佳方法是什么?
提前感谢任何能够提供帮助的人!!
我的三个文件的代码如下,供参考:
write_struct.py
:
"""
write_struct.py
"""
from ctypes import *
libc = cdll.LoadLibrary("libc.so.6")
class DataStruct(Structure):
_fields_ = [("git", c_int),
("command", c_char_p)
]
def main():
pydata = DataStruct(1, c_char_p("cp file1 file2"))
libc.fopen.argtypes = c_char_p, c_char_p
libc.fopen.restype = c_void_p
libc.fwrite = libc.fwrite
libc.fwrite.argtypes = c_void_p, c_size_t, c_size_t, c_void_p
libc.fwrite.restype = c_size_t
libc.fclose = libc.fclose
libc.fclose.argtypes = c_void_p,
libc.fclose.restype = c_int
f = libc.fopen("stored_data", "wb")
libc.fwrite(byref(pydata), sizeof(pydata), 1, f)
libc.fclose(f)
return 0
main()
read_struct.c
:
/*
* read_struct.c
*
*/
#include "read_struct.h"
int main()
{
data_struct cdata = malloc(DATASIZE);
FILE *fp;
if ((fp = fopen("stored_data", "r")) != NULL) {
fread(cdata, DATASIZE, 1, fp);
printf("git: %i\n", cdata->git);
printf("command:");
printf("%s\n", cdata->command);
fclose(fp);
} else {
printf("Could not open file\n");
exit(1);
}
return 0;
}
read_struct.h
:
/*
* read_struct.h
*
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct _data_struct *data_struct;
struct _data_struct {
int git;
char command[40];
};
#define DATASIZE sizeof(struct _data_struct)
可以直接用Python写入二进制数据。 ctypes
可用于创建结构并支持位字段和联合,或者对于简单结构,可以使用 struct
模块。
from ctypes import *
class DataStruct(Structure):
_fields_ = [("git", c_int),
("command", c_char * 40)] # You want array here, not pointer
pydata = DataStruct(1,b'cp file1 file2') # byte string for initialization.
with open('stored_data','wb') as f: # write file in binary mode
f.write(pydata) # ctypes support conversion to bytes
import struct
# See struct docs for formatting codes
# i = int (native-endian. Use <i to force little-endian, >i for big-endian)
# 40s = char[40] (zero-padded if initializer is shorter)
pydata = struct.pack('i40s',1,b'cp file1 file2')
with open('stored_data2','wb') as f:
f.write(pydata)
参考:https://docs.python.org/3/library/struct.html#format-strings