I am trying to create a python object in c++ and put it in a file to be used by another program. the problem I am facing that PyObject is a pointer and I don't know how to save a pointer to a file and reload it later. I have tried multiple solutions but nothing works for me, boost for example.
func = PyDict_GetItemString(dict, "create_and_train");
pValue = PyObject_CallFunctionObjArgs(func, PyUnicode_FromString(file_path.c_str()), PyLong_FromLong(size), NULL);
//return feature_values, training_set
if (pValue != NULL)
{
PyObject *object = PyTuple_GetItem(pValue, 0);
}
I want to save object pointer to a file and load it later.
Could any one help me? thanks in advance.
Pointers are basically addresses of memory. Since they are dynamically allocated (meaning where ever there is space in the memory when you plan on executing it). This means that unless you are guaranteed that the location will not change whatsoever, you cant use a saved pointer.
One option is to copy the object's memory footprint to the file in binary. This means that you can load the whole object from the file at once at runtime. But be careful because if the object has pointers, it might not work properly because of the reason I stated before.
Saving the object's memory footprint is pretty simple,
std::ofstream file("sim.bin", std::ios::binary);
if (!file.is_open()) return; // Bail if failed.
// Dummy object as an example.
struct DummyObject { int x = 100; };
DummyObject obj;
file.write(reinterpret_cast<char*>(&obj), sizeof(DummyObject));
file.close();
And when loading the content,
std::ifstream iFile("sim.bin", std::ios::binary);
if (!iFile.is_open()) return; // Bail if failed.
DummyObject iobj;
iFile.read(reinterpret_cast<char*>(&iobj), sizeof(DummyObject));
iFile.close();
Now if that DummyObject had a pointer to some other thing, then we need to copy the content of that data to the file too. It'll slightly complicate things.
Related
This problem has bugged me for several days now, and I just cant figure it out. What I am trying to do is get an Entity from the entityMap and make a copy of it. An Entity is essentialy a map of components, so I looped through each component and made a copy of it. I debugged the program, and it worked fine until the very last line, where it said "read access violation this was 0xFFFFFFFFFFFFFFF7." It was very strange as everything was initialized (I checked the debugger)
if (entityMap.find(classname) != entityMap.end()) {
std::shared_ptr<Entity> & prefab = entityMap[classname];
std::shared_ptr<Entity> entity = std::shared_ptr<Entity>(new Entity());
for (auto & component : prefab->GetComponentMap()) {
Component * compPtr = component.second.get();
std::cout << compPtr->GetMemorySize() << "\n";
size_t size = sizeof(compPtr->GetMemorySize());
void * buffer = operator new(size);
memcpy(buffer, compPtr, size);
std::shared_ptr<Component> newComponent = std::shared_ptr<Component>(reinterpret_cast<Component *>(buffer));
entity->AddComponent(newComponent);
newComponent->SetOwner(entity);
}
Here is the offending line
newComponent->SetOwner(entity);
Here is all it does, setting the owner instance variable to the passed in parameter. That was where the debugger complained and sent me to file "memory" at _Decref method.
void Component::SetOwner(std::shared_ptr<Entity> owner) {
this->owner = owner;
}
The problem here is that you can’t copy objects just by copying the memory. For basic plain data objects without any constructors, destructors, or pointers this may work but for anything more complex it most likely won’t.
For example, if the object contains pointers to data and these are released in a destructor then the data is not deep copied, rather the pointer is, and you get double free and also possible pointers to unallocated memory. If the object relies on something being done in the constructor it is never done when copying memory. And depending on how the size is calculated it may not even be a complete copy.
This is why you should always provide a cloning mechanism in the class that takes care of these issues in a way that suits the object and makes sure there’s proper deep/shallow copying depending on the contents.
I'm currently developing application using gSoap library and has some misunderstanding of proper usage library. I has generated proxy object (-j flag) which wrapped my own classes, as you can see below. Application must work 24/7 and connect simultaneously to many cameras (~50 cameras), so after every request i need to clear all temporary data. Is it normal usage to call soap_destroy() and soap_end() after every request? Because it seem's overkill to do it after each request. May be exists another option of proper usage?
DeviceBindingProxy::destroy()
{
soap_destroy(this->soap);
soap_end(this->soap);
}
class OnvifDeviceService : public Domain::IDeviceService
{
public:
OnvifDeviceService()
: m_deviceProxy(new DeviceBindingProxy)
{
soap_register_plugin(m_deviceProxy->soap, soap_wsse);
}
int OnvifDeviceService::getDeviceInformation(const Access::Domain::Endpoint &endpoint, Domain::DeviceInformation *information)
{
_tds__GetDeviceInformation tds__GetDeviceInformation;
_tds__GetDeviceInformationResponse tds__GetDeviceInformationResponse;
setupUserPasswordToProxy(endpoint);
m_deviceProxy->soap_endpoint = endpoint.endpoint().c_str();
int result = m_deviceProxy->GetDeviceInformation(&tds__GetDeviceInformation, tds__GetDeviceInformationResponse);
m_deviceProxy->soap_endpoint = NULL;
if (result != SOAP_OK) {
Common::Infrastructure::printSoapError("Fail to get device information.", m_deviceProxy->soap);
m_deviceProxy->destroy();
return -1;
}
*information = Domain::DeviceInformation(tds__GetDeviceInformationResponse.Manufacturer,
tds__GetDeviceInformationResponse.Model,
tds__GetDeviceInformationResponse.FirmwareVersion);
m_deviceProxy->destroy();
return 0;
}
}
To ensure proper allocation and deallocation of managed data:
soap_destroy(soap);
soap_end(soap);
You want to do this often to avoid memory to fill up with old data. These calls remove all deserialized data and data you allocated with the soap_new_X() and soap_malloc() functions.
All managed allocations are deleted with soap_destroy() followed by soap_end(). After that, you can start allocating again and delete again, etc.
To allocate managed data:
SomeClass *obj = soap_new_SomeClass(soap);
You can use soap_malloc for raw managed allocation, or to allocate an array of pointers, or a C string:
const char *s = soap_malloc(soap, 100);
Remember that malloc is not safe in C++. Better is to allocate std::string with:
std::string *s = soap_new_std__string(soap);
Arrays can be allocated with the second parameter, e.g. an array of 10 strings:
std::string *s = soap_new_std__string(soap, 10);
If you want to preserve data that otherwise gets deleted with these calls, use:
soap_unlink(soap, obj);
Now obj can be removed later with delete obj. But be aware that all pointer members in obj that point to managed data have become invalid after soap_destroy() and soap_end(). So you may have to invoke soap_unlink() on these members or risk dangling pointers.
A new cool feature of gSOAP is to generate deep copy and delete function for any data structures automatically, which saves a HUGE amount of coding time:
SomeClass *otherobj = soap_dup_SomeClass(NULL, obj);
This duplicates obj to unmanaged heap space. This is a deep copy that checks for cycles in the object graph and removes such cycles to avoid deletion issues. You can also duplicate the whole (cyclic) managed object to another context by using soap instead of NULL for the first argument of soap_dup_SomeClass.
To deep delete:
soap_del_SomeClass(obj);
This deletes obj but also the data pointed to by its members, and so on.
To use the soap_dup_X and soap_del_X functions use soapcpp2 with options -Ec and -Ed, respectively.
In principle, static and stack-allocated data can be serialized just as well. But consider using the managed heap instead.
See https://www.genivia.com/doc/databinding/html/index.html#memory2 for more details and examples.
Hope this helps.
The way memory has to be handled is described in Section 9.3 of the GSoap documentation.
I wrote a program, which lets you enter information about a car, and then writes the object on a binary file.
Car car_obj; std::ofstream entr; std::ifstream ex;
void save_data() {
entr.open("main.bin", std::ios::app | std::ios::binary);
car_obj.setInfo(); entr.write((char*)&car_obj, sizeof (car_obj));
entr.close();
}
After this, I have a function which is reading this binary file in order to display all cars which have fuel consumption less than what the user enters (the number is factr in the function arguments).
void vehicles_under_factr(float factr) {
ex.open("main.bin", std::ios::app | std::ios::binary);
while (ex.read((char*)&car_obj, sizeof (car_obj)) && !ex.eof()) {
if (car_obj.fuel_cons < factr) {
car_obj.displayInfo();
}
}
ex.close();
}
It works fine, but only if I have three, or less, objects in my binary file. When there are more than three, it displays the rest as empty fields. As if there is no access after the third car. Why is that so, and what can I do about it?
I feel close to the solution, but my knowledge is limited. Thank you in advance!
no, you can't do this,read((char *)obj, sizeof(obj)),because every object in program have itself memory address, allocate by system. you can't read address
from file .if your object only contain data, it work fine, but if it's element is a object and itself attribute related memory address or iterator(related memory address). it work fail.
I have made a class Flight with informations to be stored in a binary file called data.txt at another method.That saving of records was working fine, but now I'm having problems reading back the records I've saved. It is working to display all the records till the end of the file (eof). But when records are done displaying, there comes a pop up error saying that Program.exe has stopped working.
void Flight::ViewFlight(){
HANDLE hConsole; //Console colors
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
fstream data;
Flight flight;
data.open("data.txt",ios::in | ios::binary);
if (data.fail())
{
SetConsoleTextAttribute(hConsole, 12);
cout<<"\n\nFlight data does not exist yet";
cout<<"\n\nYou are being redirected to the Main Menu in 3 seconds\n\n";
cout<<"3\n\n";
Sleep(1000);
cout<<"2\n\n";
Sleep(1000);
cout<<"1\n\n";
Sleep(1000);
cout<<"0\n\n";
SetConsoleTextAttribute(hConsole, 15);
}
else{
while(data.read((char*) &flight, sizeof(flight)))
{
if(!data.eof())
{
SetConsoleTextAttribute(hConsole, 10);
cout<<"\n\n----------- Record for "<<flight.flightid<<" -----------\n";
SetConsoleTextAttribute(hConsole, 15);
cout<<"\nFlight Number \t\t: "<<flight.flightnumber;
cout<<"\nDeparture Airport\t: "<<flight.departAirport;
cout<<"\nArrival Airport\t\t: "<<flight.arriveAirport;
cout<<"\nDeparture Time\t\t: "<<flight.departTime.hour<<":"<<flight.departTime.minute;
cout<<"\nDeparture Date\t\t: "<<flight.departDate.day<<"/"<<flight.departDate.month<<"/"<<flight.departDate.year;
cout<<"\nPrice \t\t\t: RM "<<flight.price;
cout<<"\nBusiness Class Seats\t: "<<flight.bseat;
cout<<"\nFirst Class Seats\t: "<<flight.fseat;
cout<<"\nEconomy Class Seats\t: "<<flight.totalseat;
cout<<endl;
}
}
}
data.close();
}
Your Flight class contains std::string members. These are not plain old data types and typically hold pointers to dynamically allocated memory. You can't read and write your class as a unit and hope the std::string members and their contents will be properly constructed. The same may apply to the Time and Data members but you haven't shown how they're defined.
You need to look into proper serialization.
Several related questions:
Serializing a class which contains a std::string
How to write strings as binaries to file?
Question about read and write std::string to Binary Files
The loop seems fine, your file might have corrupted data, probably a not terminated string, or may be there is/are some garbage characters at the end of the input file. to verify comment all the cout statements in the loop, and see if the program stops hanging.
also data.eof() check is redundant, nevertheless it should not hang the program.
just had a look at your flight class, you can not read directly into a class having other class objects. in your case, the string objects. you need to deserliaze the stream and initilize the variables yourself
The problem is when the Flight is getting destructed it is destroying those string objects which are not correctly constructed string objects.
Basically first separate your character strings from your buffer and assign those to your string variables one by one yourself.
Flight structure consist of other classes that point to dynamically allocated memory (heap), for example string flightnumber; is STL string class, that has char* or wchar* inside.
If you save Flight object as a binary buffer, it will save pointer only. While loading the object, you'll get memory address in the pointer, that is invalid. That's the reason you are getting access violation exception, that means you tried to access not allocated memory.
btw that's the best case you got 0xC0000005, in worst case you'd just access memory allocated for other objects, and got trash in your output.
You have to overload operator<< and operator>> for Flight class, and every class member which is not standard library. After you do it you'll just write:
fstream data;
Flight flight;
data >> flight;
What is the correct way to declare and use a FILE * pointer in C/C++? Should it be declared global or local? Can somebody show a good example?
It doesn't matter at all whether it's local or global. The scope of the file pointer has nothing to do with its use.
In general, it's a good idea to avoid global variables as much as possible.
Here's a sample showing how to copy from input.txt to output.txt:
#include <stdio.h>
int main(void) {
FILE *fin, *fout; int c;
// Open both files, fail fast if either no good.
if ((fin = fopen("input.txt", "r")) == NULL) {
fprintf(stderr, "Cannot read from input.txt");
return 1;
}
if ((fout = fopen("output.txt", "w")) == NULL) {
fprintf(stderr, "Cannot write to output.txt");
fclose(fin);
return 1;
}
// Transfer character by character.
while ((c = fgetc(fin)) >= 0) {
fputc (c, fout);
}
// Close both files and exit.
fclose(fin);
fclose(fout);
return 0;
}
It's just an ordinary pointer like any other.
FILE *CreateLogFile()
{
return fopen("logfile.txt","w"); // allocates a FILE object and returns a pointer to it
}
void UsefulFunction()
{
FILE *pLog = CreateLogFile(); // it's safe to return a pointer from a func
int resultsOfWork = DoSomeWork();
fprintf( pLog, "Work did %d\n", resultsOfWork ); // you can pass it to other functions
fclose( pLog ); // just be sure to clean it up when you are done with fclose()
pLog = NULL; // and it's a good idea to overwrite the pointer afterwards
// so it's obvious you deleted what it points to
}
Here is the first hit on google for "file io in c"
http://www.cs.bu.edu/teaching/c/file-io/intro/
Here is the third hit from gamedev with more of a C++ slant
http://www.gamedev.net/reference/articles/article1127.asp
You declare the pointer in the scope that you need it.
int main(void)
{
char c;
FILE *read;
read = fopen("myfile", "r"); // opens "myfile" for reading
if(read == NULL)
{
perror("Error: could not open \"myfile\" for reading.\n");
exit(1);
}
c = fgetc(read);
fclose(read);
printf("The first character of myfile is %c.\n", c);
return 0;
}
You're perfectly allowed to declare global filehandles if you like, just like any other variable, but it may not be recommended.
This is the C way. C++ can use this, but I think there's a more C++ friendly way of doing it. As a note, I hate it when questions are marked C/C++, because C and C++ are not the same language and do not work the same. C++ has a lot of different ways to do things that C doesn't have, and they may be easier for you to do in the context of C++ but are not valid C. So while this will work for either language, it's not what you want if you predominantly use C++.
EDIT: Added some error checking. Always use error checking in your code.
First, keep in mind that a file pointer (and the associated allocated structure) is based on the lower level open() read() write() calls. The associated file descriptor (obtained by fileno(file_pointer) is the least interesting thing, but something you might want to watch your scope with.
If your going to declare a file pointer as global in a module, its usually a very good idea to keep it static (contained within that module / object file). Sometimes this is a little easier than storing it in a structure that is passed from function to function if you need to write something in a hurry.
For instance, (bad)
#include <stdio.h>
#include ...
#define MY_LOG_FILE "file.txt"
FILE *logfile
Better done as:
#include <stdio.h>
#define MY_LOG_FILE "file.txt"
static FILE *logfile;
int main(void)
{
UNLESS, you need several modules to have access to that pointer, in which case you're better off putting it in a structure that can be passed around.
If its needed only in one module, consider declaring it in main() and letting other functions accept a file pointer as an argument. So, unless your functions within the module have so many arguments that another would be unbearable .. there's (usually) no reason to declare a file pointer globally.
Some logging libraries do it, which I don't care for ... especially when dealing with re-entrant functions. Nevermind C's monolithic namespace :)