I know this has been asked before, and I tried to implement the solution, but I just get exception errors when I call ps->executeUpdate(). Has anyone got an explicit example?
This post is a bit old, but I ran across the same question. I employed the method above and it didn't quite work right for my case, which was trying to take a vector and use that for the stream. What I was doing was taking a UUID and converting it into a 16 byte binary version to use in the table. Using the method above, I found that only half my buffer was being populated.
I ended up using a stringstream.
std::vector<unsigned char> convertedId;
std::stringstream stream;
// convertedId has been populated with the 16 byte binary version
stream = std::stringstream(std::string(convertedId.begin(), convertedId.end()));
// Parameter 1 is BINARY(16)
pStatement->setBlob(1, &stream);
A few other things to keep in mind. The stream is not accessed until one of the execute variants is called. So you'll need to keep the stream around until you have run execute.
Hopefully this will help someone and save them time.
Sorry Matthew - I assumed the previous answer to this question (by elrohin). Maybe I should have replied to that. Anyway heres the code he suggested:
class DataBuf : public streambuf
{
public:
DataBuf(char * d, size_t s) {
setg(d, d, d + s);
}
};
// prepare sql update statement etc. and set the data pointer
string* pData = ; // ...not part of the original answer
DataBuf buffer((char*)pData->data(), pData->length());
istream stream(&buffer);
ps->setBlob(1, &stream);
ps->executeUpdate(); // This causes an exception in free.c
I'm using VS9 with the latest (beta) connector/cpp debug libs. I've also tried using char* instead of string.
This code works fine for me:
Driver *driver;
Connection *conn;
driver = get_driver_instance();
conn = driver->connect("tcp://127.0.0.1:3306", "root", "root");
std::auto_ptr use_stmt(conn->createStatement());
use_stmt->execute("USE world");
std::auto_ptr stmt(conn->prepareStatement("INSERT INTO terrain_texture_tiles_0 (data) VALUES(?)"));
std::string value("A\0B", sizeof("A\0B") - 1);
std::istringstream tmp_blob(value);
stmt->setBlob(1, &tmp_blob);
stmt->execute();
hope it helps ... Jaroslav Pribyl
Related
I am following the "chat example" from Boost Asio's tutorials. As I don't have much experience with Boost Asio, I am implementing my own client server application using the chat example and modifying it according to my needs.
Now I am defining a Protocol.hpp file, which contains keywords for the network protocol. For example:
Protocol.hpp
#ifndef PROTOCOL_HPP
#define PROTOCOL_HPP
#include <iostream>
extern const char ACK;
#endif
Protocol.cpp
#include "Protocol.hpp"
const char ACK = "1";
If you take a look at the "chat_message.hpp" class, you will find the following:
const char* data() const
{
return data_;
}
char* data()
{
return data_;
}
I have tried the following:
std::sprintf(write_msgs_.data(), ACK, 2);
As well as trying to assign directly the desired code like this —however I guess that I am obtaining the const function—:
write_msgs_.data() = ACK;
I have thought of using the string class and then somehow convert it to char, in order to copy it in the write_msgs_.data(), or even adding every character with a loop. I am relatively new to C++, and I don't seem to find a good solution for this. Is there any proper way of doing this?
Thank you very much in advance.
I found it. I should have checked how the example application does it, and it simply uses memcpy from the cstring library. Therefore, anyone having the same problem as me should use the following:
main of the chat_client.cpp file:
char line[chat_message::max_body_length + 1];
while (std::cin.getline(line, chat_message::max_body_length + 1))
{
using namespace std; // For strlen and memcpy.
chat_message msg;
msg.body_length(strlen(line));
memcpy(msg.body(), line, msg.body_length());
msg.encode_header();
c.write(msg);
}
As you can see there is a char line variable that will hold the written text. After this, memcpy is used to copy the line to the body of the message.
I dont understand the mistake I am making.
I tryed alot but I am unable to read my FILE.
Basically I write an structure into a file named 0.txt / 1.txt / 2.txt ... based of account amound.
I realy seached hours to fix my problem but I dont understand how I can fix and why I get the ERROR.
Also I have no problem in complining my code (with dev c++) but when I press on Load Accounts Button I get the ERROR "Segmentation Fault" (using windows 7).
I noticed that the problem is at fread() line in function ladeAccounts().
The name of my Structure is "iAccount".
The variable infoma is as iAccount typed and the "number of accounts existing" typed as int anzahl in newAccount() decides the path.
iAccount looks like this:
struct iAccount
{
string ID;
string password;
int level;
};
This is how I write my STRUCT into the FILE:
void Account::newAccount(int anzahl, string username, string pw, int lvl)
{
iAccount neu;
neu.ID = username;
neu.password = pw;
neu.level = lvl;
ss.str("");
ss<<anzahl;
s = ss.str();
s = "Accounts/"+s+".txt";
f1 = fopen(s.c_str(), "w");
fseek(f1, 0, SEEK_SET);
fwrite(&infoma, sizeof(iAccount), 1, f1);
fclose(f1);
}
This is how I read the File (ERROR APPEARS when I call fread()
void Account::ladeAccount(int nummer)
{
stringstream sa;
iAccount account_geladen;
sa.str("");
sa<<nummer;
s = sa.str();
s = "Accounts/"+s+".txt";
f2 = fopen(s.c_str(), "r");
fseek(f2, 0, SEEK_SET);
fread(&infoma, sizeof(infoma), 1, f2);
fclose(f2);
}
Thank you for your help. I have no clue where my problem is and as I said I am searching for hours.
EDIT:
The file gets opened I tryed it (f2 is true!).
EDIT":
ERRNO = 0 !!!
SEE HERE:
ostringstream Str;
Str << errno;
infoma.ID = Str.str();
Just did this to see the result of errno in my wxtextlabel.
Reason
You are most probably calling fread on a NULL file handle. So you have two problems here:
In your code (you don't check if fread succeeds or returns a NULL value)
Your file can't be opened for some reason (this, you should investigate...)
Explication
fopen (see documentation) can return a NULL handle for different reasons. If you don't check the validity of the handle before calling fread you will have a segmentation fault.
Tips
As you can read in the official documentation I linked above, on most library implementations the errno variable can help you giving the system-specific error code on failure. This could help you debugging your error in opening the file.
Side Issues
Once you solve this bug in our code you will have other issues. As people (notably #Christophe) remarked in other answers, there is a structural problem in your code because you try to serialize/deserialize on your file objects non POD (aka your strings). Since string are complex objects you can't serialize them directly.
The approach of using an array of characters will work correctly, as simple types can be handled the way you coded.
For this reason, you can use the std::string c_str() method to obtain a null terminated array of chars from your string and store it in the file.
The opposite operation is even more straightforward, as you can initialize a std::string simply passing the deserialized array of chars:
std::string str(the_array);
You have a problem because you use fread() to load binary data. But this works only with plain old data (POD) objects.
It uses to give desastrous results with less trivial objects especially if the internals of these manage dynamic memory allocaton and/or pointers like it's the case here with strings.
By the way:
If you read/write binary data, you should really use "rb"/"wb" as mode for fopen(). If you don't you would'nt necessary have a seg.fault, but your data might be incorrect on some systems.
Edit:
Sorry, I didn't read well enough: if it happens right at fread() the reason provided by Alex will certainly help. However I leave this answer because as soon as you've solved your fopen() issue, you might get segmentation errors if you try to work with the object that you've read. If you're not conviced, look at sizeof(iAccount) and compare it to the size your string content.
EDIT
if(f2) is true so I am wrong and file got opened successfull right?
I found out that the file is not opened/the fopen can not handle with the path for example 0.txt .
Also I tryed to enter the path directly without building it (without stringstream and so on). Still I have the problem of the segmentation fault. I checked everything the file exists in the folder Accounts. I have an other file called "Accounts.txt" in the same folder and there I have no problem reading the amound of accounts existing (also using a struct). There I dont even check if the fopen had success but it works anyway I will write the code for the file-open-check later.
The code for the reading/writing into Accounts/Accounts.txt is:
struct init{
int anzahl_1;};
init anzahl;
FILE* f;
static string ss = "Accounts/Accounts.txt";
int account_anzahl1()
{
f = fopen(ss.c_str(), "r");
fread(&anzahl, sizeof(init), 1, f);
fseek(f, 0, SEEK_END);
fclose(f);
return anzahl.anzahl_1;
}
void account_anzahl_plus()
{
anzahl.anzahl_1 = anzahl.anzahl_1 +1;
f = fopen(ss.c_str(), "w");
fwrite(&anzahl, sizeof(init), 1, f);
fclose(f);
}
There I have no problem!
when I use ostringstream, the only value that i get is : COM1
I have an application, which sends data.
I am using the code as :
std::ostringstream values;
values << someStruct.someValues;
...
...
std::string data
data << values.str();
But when I run this, all I get is an output saying COM1. My application is a DLL file.
But when I do this method below, I get the correct values
char *data;
char values[20];
sprintf(values, "%d",someStruct.someValue);
strcat(data,values);
But I don't want to use the above method as I have many variables that I need to fetch from the program. So someone please help.
std::string data;
data << values.str();
std::string is not a stream. It can't take operator<<. I'm surprised this code even compiles, but it almost certainly doesn't do something useful. What you want is this:
std::string data = values.str();
For the following C++ and ActionScript3 code, my AIR application crashes when the getBytes2 method is called. Why is this happening? Solution suggestions would be appreciated.
C++ Code:
FREObject getBytes2(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
FREObject result;
FREByteArray actualBytes;
FREAcquireByteArray(argv[0], &actualBytes);
uint8_t* nativeString = (uint8_t*) "Hello World from C++";
memcpy(actualBytes.bytes, nativeString, sizeof(nativeString));
FREReleaseByteArray(&actualBytes);
FRENewObjectFromBool(1, &result);
return result;
}
ActionScript3 Code:
public function getBytes2():ByteArray {
var ba:ByteArray = new ByteArray();
this._ExtensionContext.call("getBytes2", ba);
ba.position = 0;
return ba;
}
See FREImageProcessor.cpp for a working example of dynamically setting the length. Basically you set the length the same way you would in ActionScript.
FREObject length;
FRENewObjectFromUint32(sizeof(nativeString), &length);
FRESetObjectProperty(argv[0], (const uint8_t*) "length", length, NULL);
Are you getting any particular error or crash message? Which IDE are you using -- is it possible to attach the debugger on that process? I would put my money on the crash being during the memcpy function...
My only though it that while you are sending the string, you are not copying the null terminator from the string to your BA. I don't think that should matter however (you may experience extracting the data on the AS3 side, but that shouldn't cause an issue).
There were actually some people reporting similar issues when they were getting the byteArrays. I have a kludgy fix I haven't posted in the ArduinoConnector code for it yet. Pretty much involves seeding a 4096 byte byteArray on the AS3 side and sending that in. I also tried by just creating a new byteArray in the c side with similar results. According to the AIR engineers, we shouldn't have this problem, but I don't know if they accounted for how the memcpy function works.
I'm trying to serialize objects to send over network through a socket using only STL. I'm not finding a way to keep objects' structure to be deserialized in the other host. I tried converting to string, to char* and I've spent a long time searching for tutorials on the internet and until now I have found nothing.
Is there a way to do it only with STL?
Are there any good tutorials?
I am almost trying boost, but if there is how to do it with STL I'd like to learn.
You can serialize with anything. All serialization means is that you are converting the object to bytes so that you can send it over a stream (like an std::ostream) and read it with another (like an std::istream). Just override operator <<(std::ostream&, const T&) and operator >>(std::istream&, T&) where T is each of your types. And all the types contained in your types.
However, you should probably just use an already-existing library (Boost is pretty nice). There are tons of things that a library like Boost does for you, like byte-ordering, taking care of common objects (like arrays and all the stuff from the standard library), providing a consistent means of performing serialization and tons of other stuff.
My first question will be: do you want serialization or messaging ?
It might seem stupid at first, since you asked for serialization, but then I have always distinguished the two terms.
Serialization is about taking a snapshot of your memory and restoring it later on. Each object is represented as a separate entity (though they might be composed)
Messaging is about sending information from one point to another. The message usually has its own grammar and may not reflect the organization of your Business Model.
Too often I've seen people using Serialization where Messaging should have been used. It does not mean that Serialization is useless, but it does mean that you should think ahead of times. It's quite difficult to alter the BOM once you have decided to serialize it, especially if you decide to relocate some part of information (move it from one object to another)... because how then are you going to decode the "old" serialized version ?
Now that that's been cleared up...
... I will recommend Google's Protocol Buffer.
You could perfectly rewrite your own using the STL, but you would end up doing work that has already been done, and unless you wish to learn from it, it's quite pointless.
One great thing about protobuf is that it's language agnostic in a way: ie you can generate the encoder/decoder of a given message for C++, Java or Python. The use of Python is nice for message injection (testing) or message decoding (to check the output of a logged message). It's not something that would come easy were you to use the STL.
Serializing C++ Objects over a Network Socket
This is 6 years late but I just recently had this problem and this was one of the threads that I came across in my search on how to serialize object through a network socket in C++. This solution uses just 2 or 3 lines of code. There are a lot of answers that I found work but the easiest that I found was to use reinterpret_cast<obj*>(target) to convert the class or structure into an array of characters and feed it through the socket. Here's an example.
Class to be serialized:
/* myclass.h */
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass
{
public:
int A;
int B;
MyClass(){A=1;B=2;}
~MyClass(){}
};
#endif
Server Program:
/* server.cpp */
#include "myclass.h"
int main (int argc, char** argv)
{
// Open socket connection.
// ...
// Loop continuously until terminated.
while(1)
{
// Read serialized data from socket.
char buf[sizeof(MyClass)];
read(newsockfd,buf, sizeof(MyClass));
MyClass *msg = reinterpret_cast<MyClass*>(buf);
std::cout << "A = " << std::to_string(msg->A) << std::endl;
std::cout << "B = " << std::to_string(msg->B) << std::endl;
}
// Close socket connection.
// ...
return 0;
}
Client Program:
/* client.cpp */
#include "myClass.h"
int main(int argc, char *argv[])
{
// Open socket connection.
// ...
while(1)
{
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
MyClass msg;
msg.A = 1;
msg.B = 2;
// Write serialized data to socket.
char* tmp = reinterpret_cast<char*>(&msg);
write(sockfd,tmp, sizeof(MyClass));
}
// Close socket connection.
// ...
return 0;
}
Compile both server.cpp and client.cpp using g++ with -std=c++11 as an option. You can then open two terminals and run both programs, however, start the server program before the client so that it has something to connect to.
Hope this helps.
I got it!
I used strinstream to serialize objects and I sent it as a message using the stringstream's method str() and so string's c_str().
Look.
class Object {
public:
int a;
string b;
void methodSample1 ();
void methosSample2 ();
friend ostream& operator<< (ostream& out, Object& object) {
out << object.a << " " << object.b; //The space (" ") is necessari for separete elements
return out;
}
friend istream& operator>> (istream& in, Object& object) {
in >> object.a;
in >> object.b;
return in;
}
};
/* Server side */
int main () {
Object o;
stringstream ss;
o.a = 1;
o.b = 2;
ss << o; //serialize
write (socket, ss.str().c_str(), 20); //send - the buffer size must be adjusted, it's a sample
}
/* Client side */
int main () {
Object o2;
stringstream ss2;
char buffer[20];
string temp;
read (socket, buffer, 20); //receive
temp.assign(buffer);
ss << temp;
ss >> o2; //unserialize
}
I'm not sure if is necessary convert to string before to serialize (ss << o), maybe is possible directly from char.
I think you should use google Protocol Buffers in your project.In network transport Protocol buffers have many advantages over XML for serializing structured data. Protocol buffers:
are simpler
are 3 to 10 times smaller
are 20 to 100 times faster
are less ambiguous
generate data access classes that are easier to use programmaticall
and so on. I think you need read https://developers.google.com/protocol-buffers/docs/overview about protobuf