python - 使用 Python C 模块编写 Bin 文件并在 C 中读取文件
问题描述
我ctypes
用来转换二进制文件中的一些信息,这些信息需要由 C++ 程序读取。该文件将包含带有字符串的行和其他带有双精度/双精度向量的行。
当我尝试在 C++ 中读取双精度向量时会出现问题:向量的地址位于行尾,地址有 11 个字符,而 C++ 中有 8 个字符。当我尝试将向量直接读入 C++ 时,由于这种差异会发生错误。
一种可能的解决方案是逐个元素地读取向量,但这会降低性能。
有没有可能在转换和读取过程中撕掉地址,或者忽略它,以及整个向量?
这是我们用来测试的一些代码:
C++ DLL 模块:
#include<iostream>
#include<fstream>
#include<cstring>
#include <typeinfo>
using namespace std;
#define DLLEXPORT extern "C" __declspec(dllexport)
struct new_element {
int id;
unsigned int n_measures;
double* value;
};
DLLEXPORT int writer_bin_file_c(const char* file_path, new_element structed_data)
{
try {
ofstream output_file(file_path);
output_file.write((char*)&structed_data, sizeof(structed_data));
output_file << &structed_data;
output_file.close();
} catch (...) {
return -1;
}
return 0;
}
DLLEXPORT new_element reader_bin_file_c(const char* file_path, new_element structed_data)
{
try {
ifstream input_file(file_path, ios::binary);
input_file.read((char*)&structed_data, sizeof(structed_data));
input_file.close();
} catch (...) {
cout << "Error ao ler o arquivo" << endl;
}
return structed_data;
}
Python写入文件:
from ctypes import *
import sys
import numpy as np
lib = CDLL("version4/template_file.so")
class new_element(Structure):
_fields_ = [("id", c_int),
("n_measures", c_uint),
("value", POINTER(c_double))]
template_file = lib
new_element_pointer = POINTER(new_element)
writer_bin_file = template_file.writer_bin_file_c
writer_bin_file.argtypes = [c_char_p, new_element]
writer_bin_file.restype = c_void_p
reader_bin_file_c = template_file.reader_bin_file_c
reader_bin_file_c.restype = new_element
tam = 10
medida = np.arange(tam, dtype=c_double)
medida = medida.ctypes.data_as(POINTER(c_double))
element = new_element(4, tam)
element.value = medida
file_out = b'version4/element.txt'
answer = writer_bin_file(file_out, element)
C++ 读取文件:
#include<iostream>
#include<fstream>
#include<cstring>
#include <typeinfo>
using namespace std;
struct new_element {
int id;
unsigned int n_measures;
double* value;
};
new_element reader_bin_file(const char* file_path, new_element structed_data)
{
try {
ifstream input_file(file_path);
input_file.read((char*)&structed_data, sizeof(structed_data));
input_file.close();
} catch (...) {
cout << "Error ao ler o arquivo" << endl;
}
return structed_data;
}
int main(int argc, char const *argv[])
{
new_element read_template;
read_template = reader_bin_file(file_out, read_template);
cout << "ID: " << read_template.id << endl;
cout << "n_measures: " << read_template.n_measures << endl;
cout << "Value: ";
for (int i = 0; i < read_template.n_measures; i++)
{
cout << "( " << i << " ): " << read_template.value[i] << " | ";
}
cout << endl;
return 0;
}
解决方案
你在这里有一个深刻的误解。
一对字段
unsigned int n_measures;
double* value;
是一个数组(从他们的名字推导出来),所以在编写器中你必须保存n_measures
双精度值,而不是单个指针。因此,在阅读器中,您应该读取 n_measures
值,而不仅仅是指针。指针只是内存空间中的一个索引,而不是一些“全能”的 C/C++ 语言功能,它可以保存您需要的一切。
所以,在你的 C++ 编写代码中
DLLEXPORT int writer_bin_file_c(const char* file_path, new_element structed_data)
{
try {
ofstream output_file(file_path);
output_file.write((char*)&structed_data.id, sizeof(int));
output_file.write((char*)&structed_data.n_measures, sizeof(int));
// write out all the elements one by one, not just the pointer
for (int i = 0 ; i < structed_data.n_measures ; i++)
output_file.write((char *)&structed_data[i], sizeof(double));
output_file.close();
} catch (...) {
return -1;
}
return 0;
}
希望你明白,至少在 C++ 部分。读取器代码类似——读取id
,n_measures
然后分配values
数组并一一读取值。
推荐阅读
- python - Pypy3用字典慢
- php - 未定义的变量:apcu php 脚本的配置和问题
- automation - 如何在 AutoHotkey 中制作一个代码,所有打开的程序都接收某个热键?
- laravel - Laravel Queue:多队列、多任务、多远程服务器
- c++ - 无法初始化 SDL2,但 SDL_GetError() 不返回任何内容
- algorithm - 什么是实现 APL 升级的高性能算法?
- node.js - 如何使用 Express Handlebars 模板引擎从 mongoDB 检索和更新图像?
- multithreading - 为什么 epoll 线程安全而不是 libevent
- javascript - 为什么使用模块时浏览器中的窗口无法访问类的实例?
- c# - 有没有办法从 AWS 开发工具包中检索 AWS 凭证信息?