Я предполагаю, что вы имеете в виду «приложение X11» - из вашего описания не совсем ясно, что вы планируете делать. Ниже фрагмент кода отправит код «паузы» в приложение, которое в настоящее время имеет фокус ввода с клавиатуры в X11, используя расширение XTest. Из того, что я прочитал, это наиболее совместимый способ «подделать» события клавиатуры. Посмотрите, можете ли вы применить это к вашему сценарию (нет ошибки проверки правильности XOpenDisplay, чтобы сделать его проще).
#include & lt; X11 / Xlib.h & gt; #include & lt; X11 / keysym.h & gt; #include & lt; X11 / extensions / XTest.h & gt; ... Показать * дисплей; unsigned int keycode; display = XOpenDisplay (NULL); ... keycode = XKeysymToKeycode (отображение, XK_Pause); XTestFakeKeyEvent (отображение, keycode, True, 0); XTestFakeKeyEvent (отображение, код ключа, False, 0); XFlush (дисплей);
Вам нужно будет связать с -lX11 -lXtst.
Очевидно, что firefox должен был иметь фокус в это время.
Однако , Мне было бы интересно узнать, что является более сложной задачей, которую вы пытаетесь выполнить - я подозреваю, что должно быть более элегантное решение, чем подделка событий нажатия клавиш.
Я сериализую, отбрасывая класс в char * и записывая его в файл с файлом fstream. Чтение, конечно, только наоборот.
blockquote>К сожалению, это работает только при отсутствии указателей. Вы можете указать свои классы
void MyClass::serialize(std::ostream)
иvoid MyClass::deserialize(std::ifstream)
и вызвать их. Для этого случая вам нужноstd::ostream& MyClass::serialize(std::ostream &out) const { out << height; out << ',' //number seperator out << width; out << ',' //number seperator out << name.size(); //serialize size of string out << ',' //number seperator out << name; //serialize characters of string return out; } std::istream& MyClass::deserialize(std::istream &in) { if (in) { int len=0; char comma; in >> height; in >> comma; //read in the seperator in >> width; in >> comma; //read in the seperator in >> len; //deserialize size of string in >> comma; //read in the seperator if (in && len) { std::vector<char> tmp(len); in.read(tmp.data() , len); //deserialize characters of string name.assign(tmp.data(), len); } } return in; }
. Вы также можете перегрузить операторы потока для более удобного использования.
std::ostream &operator<<(std::ostream& out, const MyClass &obj) {obj.serialize(out); return out;} std::istream &operator>>(std::istream& in, MyClass &obj) {obj.deserialize(in); return in;}
Самый простой способ сериализации для строк или других блоков с переменным размером - это сериализовать сначала размер при сериализации целых чисел, а затем просто скопировать содержимое в выходной поток.
При чтении сначала читайте размер , затем выделите строку и затем заполните ее, прочитав правильное количество байтов из потока.
Альтернативой является использование разделителя и экранирования, но для этого требуется больше кода и медленнее как при сериализации, так и при десериализации ( однако результат может быть сохранен для чтения человеком).
Просто запись двоичного содержимого объекта в файл не только не переносима, но, как вы признали, не работает для данных указателя. В основном у вас есть два варианта: либо вы пишете настоящую библиотеку сериализации, которая правильно обрабатывает std :: strings, например. используя c_str () , чтобы вывести фактическую строку в файл, или вы используете отличную библиотеку boostization . Если это вообще возможно, я бы рекомендовал последнее, вы можете сериализовать с помощью простого кода следующим образом:
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/string.hpp>
class A {
private:
std::string s;
public:
template<class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & s;
}
};
Здесь функция serialize
работает для сериализации и десериализации данных, в зависимости от как вы это называете. Дополнительную информацию см. В документации.
Я долго не кодировал C ++, но, возможно, вы могли бы сериализовать массив из char
.
Затем, когда вы открываете файл, ваш string
будет просто указывать на массив.
Просто идея.
/*!
* reads binary data into the string.
* @status : OK.
*/
class UReadBinaryString
{
static std::string read(std::istream &is, uint32_t size)
{
std::string returnStr;
if(size > 0)
{
CWrapPtr<char> buff(new char[size]); // custom smart pointer
is.read(reinterpret_cast<char*>(buff.m_obj), size);
returnStr.assign(buff.m_obj, size);
}
return returnStr;
}
};
class objHeader
{
public:
std::string m_ID;
// serialize
std::ostream &operator << (std::ostream &os)
{
uint32_t size = (m_ID.length());
os.write(reinterpret_cast<char*>(&size), sizeof(uint32_t));
os.write(m_ID.c_str(), size);
return os;
}
// de-serialize
std::istream &operator >> (std::istream &is)
{
uint32_t size;
is.read(reinterpret_cast<char*>(&size), sizeof(uint32_t));
m_ID = UReadBinaryString::read(is, size);
return is;
}
};
Почему не просто что-то вроде:
std::ofstream ofs;
...
ofs << my_str;
, а затем:
std::ifstream ifs;
...
ifs >> my_str;
Вам придется использовать более сложный метод сериализации, чем приведение класса к char*
и запись его в файл, если ваш класс содержит любые экзогенные данные (string
). И вы правы в том, почему вы получаете ошибку сегментации.
Я бы сделал функцию-член, которая будет принимать fstream
и читать данные из нее, а также обратную функцию, которая возьмите fstream
и напишите его содержимое для его восстановления позже, например:
class MyClass {
pubic:
MyClass() : str() { }
void serialize(ostream& out) {
out << str;
}
void restore(istream& in) {
in >> str;
}
string& data() const { return str; }
private:
string str;
};
MyClass c;
c.serialize(output);
// later
c.restore(input);
Вы также можете определить operator<<
и operator>>
для работы с istream
и ostream
для сериализации и восстановления вашего класса, если вы хотите использовать этот синтаксический сахар.
operator<<
и >>
of (i|o)stream
на string
, который определен для записи содержимого строки в файл. У вас, очевидно, было бы больше членов данных, чем одна строка, поэтому вы просто записывали их все в выходной файл, а затем читали их из входного файла в том же порядке.
– Seth Carnegie
12 August 2011 в 22:09
in.read(&name[0], len);
, что, безусловно, неправильно. Вы не можете обрабатывать строку как вектор. И даже в качестве вектора он потерпит неудачу, если len == 0. – john 12 August 2011 в 22:43char *nameValue = new char[len + 1];
. – Rudy Velthuis 12 August 2011 в 22:56