问题描述
我正在使用ctype
将一些信息转换为C ++程序需要读取的二进制文件。该文件将包含带有字符串的行和其他带有double / double向量的行。
当我尝试在C ++中读取double的向量时,就会出现问题:向量的地址位于行的末尾,地址为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编写文件: 从ctypes import * 导入系统 将numpy导入为np
lib = CDLL(“ version4 / template_file.so”)
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
的双精度值,而不是一个指针。因此,在阅读器中,您应该 read 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
数组并逐个读取值。