I am asking about veins the vehicle network simulator.
In my veins application, I want to fetch some data available on a backend server through an API call.
I tried to use curl inside initialize function and I get this error:
/home/veins/workspace.omnetpp/simple_road/simple_road: symbol lookup error: /home/veins/src/veins/src/libveins.so: undefined symbol: _ZN5veins10MyVeinsApp7callAPIENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Simulation terminated with exit code: 127 Working directory: /home/veins/workspace.omnetpp/simple_road Command line: simple_road -m -n .:../../src/veins/examples/veins:../../src/veins/src/veins --image-path=../../src/veins/images -l ../../src/veins/src/veins omnetpp.ini
Environment variables: PATH=/home/veins/src/omnetpp-5.6.2/bin::/usr/lib/ccache:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/home/veins/bin:/home/veins/src/omnetpp/bin:/home/veins/src/sumo/bin:/home/veins/src/veins/bin LD_LIBRARY_PATH=/home/veins/src/omnetpp-5.6.2/lib::/home/veins/src/veins/src: OMNETPP_IMAGE_PATH=/home/veins/src/omnetpp-5.6.2/images
Code snippets:
void MyVeinsApp::initialize(int stage)
{
DemoBaseApplLayer::initialize(stage);
if (stage == 0) {
// Initializing members and pointers of your application goes here
callAPI("posts/1");
}
else if (stage == 1) {
// Initializing members that require initialized other modules goes here
}
}
size_t writeCallBack(void* contents, size_t size, size_t nmemb, void *userp) {
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
void callAPI(string path) {
CURL* curl;
CURLcode res;
string buffer;
curl = curl_easy_init();
if(curl) {
const string url = SERVER_URL + path;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallBack);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
EV << "code: " << res << ", data: " << buffer << endl;
}
}
Related
I have some generated SPIR-V code which I want to use with the vulkan API. But I get an
Exception thrown at 0x00007FFB68D933CB (nvoglv64.dll) in vulkanCompute.exe: 0xC0000005: Access violation reading location 0x0000000000000008. when trying to create the pipline with vkCreateComputePipelines.
The API calls should be fine, because the same code works with a shader compiled with glslangValidator. Therefore I assume that the generated SPIR-V code must be illformed somehow.
I've checked the SPIR-V code with the validator tool from khronos, using spirv-val --target-env vulkan1.1 mainV.spv which exited without error. Anyhow it is also known that this tool is still incomplete.
I've also tried to use the Radeon GPU Analyzer to compile my SPIR-V code, which is also available online at the shader playground and this tool throws the error Error: Error: internal error: Bil::BilInstructionConvert::Create(60) Code Not Tested! which is not really helpful, but encourages the assumption that the code is malformed.
The SPIR-V code is unfortunately to long to post it here, but it is in the link of the shader playground.
Does anyone know what the problem is with my setting or has any idea how I can verify my SPIR-V code in a better way, without checking all 700 lines of code manually.
I don't thinkt the problem is there, but anyway here is the c++ host code:
#include "vulkan/vulkan.hpp"
#include <iostream>
#include <fstream>
#include <vector>
#define BAIL_ON_BAD_RESULT(result) \
if (VK_SUCCESS != (result)) \
{ \
fprintf(stderr, "Failure at %u %s\n", __LINE__, __FILE__); \
exit(-1); \
}
VkResult vkGetBestComputeQueueNPH(vk::PhysicalDevice &physicalDevice, uint32_t &queueFamilyIndex)
{
auto properties = physicalDevice.getQueueFamilyProperties();
int i = 0;
for (auto prop : properties)
{
vk::QueueFlags maskedFlags = (~(vk::QueueFlagBits::eTransfer | vk::QueueFlagBits::eSparseBinding) & prop.queueFlags);
if (!(vk::QueueFlagBits::eGraphics & maskedFlags) && (vk::QueueFlagBits::eCompute & maskedFlags))
{
queueFamilyIndex = i;
return VK_SUCCESS;
}
i++;
}
i = 0;
for (auto prop : properties)
{
vk::QueueFlags maskedFlags = (~(vk::QueueFlagBits::eTransfer | vk::QueueFlagBits::eSparseBinding) & prop.queueFlags);
if (vk::QueueFlagBits::eCompute & maskedFlags)
{
queueFamilyIndex = i;
return VK_SUCCESS;
}
i++;
}
return VK_ERROR_INITIALIZATION_FAILED;
}
int main(int argc, const char *const argv[])
{
(void)argc;
(void)argv;
try
{
// initialize the vk::ApplicationInfo structure
vk::ApplicationInfo applicationInfo("VecAdd", 1, "Vulkan.hpp", 1, VK_API_VERSION_1_1);
// initialize the vk::InstanceCreateInfo
std::vector<char *> layers = {
"VK_LAYER_LUNARG_api_dump",
"VK_LAYER_KHRONOS_validation"
};
vk::InstanceCreateInfo instanceCreateInfo({}, &applicationInfo, static_cast<uint32_t>(layers.size()), layers.data());
// create a UniqueInstance
vk::UniqueInstance instance = vk::createInstanceUnique(instanceCreateInfo);
auto physicalDevices = instance->enumeratePhysicalDevices();
for (auto &physicalDevice : physicalDevices)
{
auto props = physicalDevice.getProperties();
// get the QueueFamilyProperties of the first PhysicalDevice
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
uint32_t computeQueueFamilyIndex = 0;
// get the best index into queueFamiliyProperties which supports compute and stuff
BAIL_ON_BAD_RESULT(vkGetBestComputeQueueNPH(physicalDevice, computeQueueFamilyIndex));
std::vector<char *>extensions = {"VK_EXT_external_memory_host", "VK_KHR_shader_float16_int8"};
// create a UniqueDevice
float queuePriority = 0.0f;
vk::DeviceQueueCreateInfo deviceQueueCreateInfo(vk::DeviceQueueCreateFlags(), static_cast<uint32_t>(computeQueueFamilyIndex), 1, &queuePriority);
vk::StructureChain<vk::DeviceCreateInfo, vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceShaderFloat16Int8Features> createDeviceInfo = {
vk::DeviceCreateInfo(vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo, 0, nullptr, static_cast<uint32_t>(extensions.size()), extensions.data()),
vk::PhysicalDeviceFeatures2(),
vk::PhysicalDeviceShaderFloat16Int8Features()
};
createDeviceInfo.get<vk::PhysicalDeviceFeatures2>().features.setShaderInt64(true);
createDeviceInfo.get<vk::PhysicalDeviceShaderFloat16Int8Features>().setShaderInt8(true);
vk::UniqueDevice device = physicalDevice.createDeviceUnique(createDeviceInfo.get<vk::DeviceCreateInfo>());
auto memoryProperties2 = physicalDevice.getMemoryProperties2();
vk::PhysicalDeviceMemoryProperties const &memoryProperties = memoryProperties2.memoryProperties;
const int32_t bufferLength = 16384;
const uint32_t bufferSize = sizeof(int32_t) * bufferLength;
// we are going to need two buffers from this one memory
const vk::DeviceSize memorySize = bufferSize * 3;
// set memoryTypeIndex to an invalid entry in the properties.memoryTypes array
uint32_t memoryTypeIndex = VK_MAX_MEMORY_TYPES;
for (uint32_t k = 0; k < memoryProperties.memoryTypeCount; k++)
{
if ((vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent) & memoryProperties.memoryTypes[k].propertyFlags &&
(memorySize < memoryProperties.memoryHeaps[memoryProperties.memoryTypes[k].heapIndex].size))
{
memoryTypeIndex = k;
std::cout << "found memory " << memoryTypeIndex + 1 << " out of " << memoryProperties.memoryTypeCount << std::endl;
break;
}
}
BAIL_ON_BAD_RESULT(memoryTypeIndex == VK_MAX_MEMORY_TYPES ? VK_ERROR_OUT_OF_HOST_MEMORY : VK_SUCCESS);
auto memory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memorySize, memoryTypeIndex));
auto in_buffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), bufferSize, vk::BufferUsageFlagBits::eStorageBuffer, vk::SharingMode::eExclusive));
device->bindBufferMemory(in_buffer.get(), memory.get(), 0);
// create a DescriptorSetLayout
std::vector<vk::DescriptorSetLayoutBinding> descriptorSetLayoutBinding{
{0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute}};
vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), static_cast<uint32_t>(descriptorSetLayoutBinding.size()), descriptorSetLayoutBinding.data()));
std::cout << "Memory bound" << std::endl;
std::ifstream myfile;
myfile.open("shaders/MainV.spv", std::ios::ate | std::ios::binary);
if (!myfile.is_open())
{
std::cout << "File not found" << std::endl;
return EXIT_FAILURE;
}
auto size = myfile.tellg();
std::vector<unsigned int> shader_spv(size / sizeof(unsigned int));
myfile.seekg(0);
myfile.read(reinterpret_cast<char *>(shader_spv.data()), size);
myfile.close();
std::cout << "Shader size: " << shader_spv.size() << std::endl;
auto shaderModule = device->createShaderModuleUnique(vk::ShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), shader_spv.size() * sizeof(unsigned int), shader_spv.data()));
// create a PipelineLayout using that DescriptorSetLayout
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get()));
vk::ComputePipelineCreateInfo computePipelineInfo(
vk::PipelineCreateFlags(),
vk::PipelineShaderStageCreateInfo(
vk::PipelineShaderStageCreateFlags(),
vk::ShaderStageFlagBits::eCompute,
shaderModule.get(),
"_ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEE6VecAdd"),
pipelineLayout.get());
auto pipeline = device->createComputePipelineUnique(nullptr, computePipelineInfo);
auto descriptorPoolSize = vk::DescriptorPoolSize(vk::DescriptorType::eStorageBuffer, 2);
auto descriptorPool = device->createDescriptorPool(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlags(), 1, 1, &descriptorPoolSize));
auto commandPool = device->createCommandPoolUnique(vk::CommandPoolCreateInfo(vk::CommandPoolCreateFlags(), computeQueueFamilyIndex));
auto commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front());
commandBuffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit)));
commandBuffer->bindPipeline(vk::PipelineBindPoint::eCompute, pipeline.get());
commandBuffer->dispatch(bufferSize / sizeof(int32_t), 1, 1);
commandBuffer->end();
auto queue = device->getQueue(computeQueueFamilyIndex, 0);
vk::SubmitInfo submitInfo(0, nullptr, nullptr, 1, &commandBuffer.get(), 0, nullptr);
queue.submit(1, &submitInfo, vk::Fence());
queue.waitIdle();
printf("all done\nWoohooo!!!\n\n");
}
}
catch (vk::SystemError &err)
{
std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1);
}
catch (std::runtime_error &err)
{
std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1);
}
catch (...)
{
std::cout << "unknown error\n";
exit(-1);
}
return EXIT_SUCCESS;
}
Well after checking out line per line it showed that the problem is when working with pointers of pointers. For me it is still not clear from the specification that it is not allowed, but it is understandable that it does not work with logical pointers.
Still the behaviour is strange that the validator is not able to note that and that compiling the SPIRV code crashes instead of throwing a clear error message.
So in the end, it was the Shader code which was wrong.
I get a SIGSEGV in following class on the second time I call the start_receive(). It works correctly in my open() function, but seems to fail when input is received and I try restarting listen for more input:
#0 0x0000555555584154 in boost::asio::basic_io_object<boost::asio::datagram_socket_service<boost::asio::ip::udp>, true>::get_service (this=0x100007f00000000)
at /usr/include/boost/asio/basic_io_object.hpp:225
#1 0x000055555558398b in boost::asio::basic_datagram_socket<boost::asio::ip::udp, boost::asio::datagram_socket_service<boost::asio::ip::udp> >::async_receive_from<boost::asio::mutable_buffers_1, boost::_bi::bind_t<int, boost::_mfi::mf2<int, Vast::net_udpNC_MChandler, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<Vast::net_udpNC_MChandler*>, boost::arg<1> (*)(), boost::arg<2> (*)()> > > (this=0x100007f00000000, buffers=...,
sender_endpoint=..., handler=...)
at /usr/include/boost/asio/basic_datagram_socket.hpp:895
#2 0x000055555557a889 in Vast::net_udpNC_MChandler::start_receive (
this=0x7fffffff5c70) at net_udpnc_mchandler.cpp:58
#3 0x000055555557aa77 in Vast::net_udpNC_MChandler::handle_input (
this=0x7fffffff5c70, error=..., bytes_transferred=24)
at net_udpnc_mchandler.cpp:100
#4 0x000055555557abb3 in Vast::net_udpNC_MChandler::handle_buffer (
this=0x7fffffff5c70, buf=0x7fffffffdad0 "\035\300", bytes_transferred=24)
at net_udpnc_mchandler.cpp:114
#5 0x000055555556397f in test_process_encoded ()
at unittest_net_udpnc_mchandler.cpp:43
#6 0x000055555556400e in main () at unittest_net_udpnc_mchandler.cpp:101
Header:
class net_udpNC_MChandler
{
public:
net_udpNC_MChandler(ip::udp::endpoint local_endpoint);
//MChandler will run its own io_service
int open (AbstractRLNCMsgReceiver *msghandler);
int handle_buffer (char *buf, std::size_t bytes_transferred);
protected:
//Start the receiving loop
void start_receive ();
// handling incoming message
int handle_input (const boost::system::error_code& error,
std::size_t bytes_transferred);
private:
ip::udp::socket *_udp;
ip::udp::endpoint _remote_endpoint_;
ip::udp::endpoint _local_endpoint;
ip::udp::endpoint MC_address;
char _buf[VAST_BUFSIZ];
AbstractRLNCMsgReceiver *_msghandler = NULL;
io_service *_io_service;
boost::thread *_iosthread;
};
Source file:
net_udpNC_MChandler::net_udpNC_MChandler(ip::udp::endpoint local_endpoint) :
MC_address(ip::address::from_string("239.255.0.1"), 1037)
{
_io_service = new io_service();
_local_endpoint = local_endpoint;
}
int net_udpNC_MChandler::open(AbstractRLNCMsgReceiver *msghandler) {
_msghandler = msghandler;
if (_udp == NULL) {
_udp = new ip::udp::socket(*_io_service);
_udp->open(ip::udp::v4());
_udp->set_option(ip::udp::socket::reuse_address(true));
_udp->set_option(ip::multicast::join_group(MC_address.address ()));
boost::system::error_code ec;
_udp->bind(MC_address, ec);
std::cout << "net_udpnc_mchandler::open " + ec.message() << std::endl;
if (ec)
{
std::cout << "net_udpnc_mchandler:: open MC address failed" << ec.message() << std::endl;
}
//Add async receive to io_service queue
start_receive();
std::cout << "net_udpnc_mchandler::open _udp->_local_endpoint: " << _udp->local_endpoint() << " _local_endpoint" << _local_endpoint << std::endl;
//Start the thread handling async receives
_iosthread = new boost::thread(boost::bind(&boost::asio::io_service::run, _io_service));
}
return 0;
}
void net_udpNC_MChandler::start_receive()
{
_udp->async_receive_from(
boost::asio::buffer(_buf, VAST_BUFSIZ), _remote_endpoint_,
boost::bind(&net_udpNC_MChandler::handle_input, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
// handling incoming message
int net_udpNC_MChandler::handle_input (const boost::system::error_code& error,
std::size_t bytes_transferred)
{
RLNCHeader header;
if (!error)
{
//Store UDP messages
char *p = _buf;
memcpy(&header, p, sizeof(RLNCHeader));
if (RLNCHeader_factory::isRLNCHeader (header) && header.enc_packet_count > 1)
{
CPPDEBUG("net_udpnc_mchandler::handle_input: Encoded packet received" << std::endl);
process_encoded (bytes_transferred);
}
//Restart waiting for new packets
start_receive();
}
else {
CPPDEBUG("Error on UDP socket receive: " << error.message() << std::endl;);
}
return -1;
}
The strangest thing is that everything works if I use a default constructor without arguments (i.e. no local_endpoint), this SIGSEGV does not appear. But as soon as I change the constructor to the current one, I get the SIGSEGV.
The _io_service is a class object and it does not get destructed anywhere but the destructor, so I do not know how I can get a SIGSEGV for it...
Is there some requirement on the handler class that it has a no arguments constructor?
I' trying to make an identical function to "ioctl" in c++ style using boost library.
Here is my "c" style code:
int sockfd;
char * id;
struct iwreq wreq;
memset(&wreq, 0, sizeof(struct iwreq));
sprintf(wreq.ifr_name, IW_INTERFACE);
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
fprintf(stderr, "Cannot open socket \n");
fprintf(stderr, "errno = %d \n", errno);
fprintf(stderr, "Error description is : %s\n",strerror(errno));
exit(1);
}
printf("Socket opened successfully \n");
id = malloc(IW_ESSID_MAX_SIZE+1);
wreq.u.essid.pointer = id;
if (ioctl(sockfd, SIOCGIWESSID, &wreq)) {
fprintf(stderr, "Get ESSID ioctl failed \n");
fprintf(stderr, "errno = %d \n", errno);
fprintf(stderr, "Error description : %s\n",strerror(errno));
exit(2);
}
printf("IOCTL Successfull\n");
printf("ESSID is %s\n", wreq.u.essid.pointer);
I found some relevant example, but I'm not clear how to use it correctly. example
Main function:
boost::asio::ip::udp::socket socket(io_service);
struct iwreq wreq
memset(&wreq, 0, sizeof(struct iwreq));
sprintf(wreq.ifr_name, IW_INTERFACE);
id = malloc(IW_ESSID_MAX_SIZE+1);
wreq.u.essid.pointer = id;
boost::asio::detail::io_control::myCommand command;
command.set(&wreq);
boost::system::error_code ec;
socket.io_control(command, ec);
if (ec)
{
// An error occurred.
}
Custom command:
#include <boost/asio/detail/config.hpp>
#include <cstddef>
#include <boost/config.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
namespace io_control {
// I/O control command for getting number of bytes available.
class myCommand
{
public:
// Default constructor.
myCommand()
: value_(0)
{
}
// Get the name of the IO control command.
int name() const
{
return static_cast<int>(SIOCGIWESSID);
}
// Set the value of the I/O control command.
void set(struct iwreq* value)
{
value_ = static_cast<detail::ioctl_arg_type>(value);
}
// Get the current value of the I/O control command.
std::size_t get() const
{
return static_cast<struct iwreq*>(value_);
}
// Get the address of the command data.
detail::ioctl_arg_type* data()
{
return &value_;
}
// Get the address of the command data.
const detail::ioctl_arg_type* data() const
{
return &value_;
}
private:
detail::ioctl_arg_type value_;
};
} // namespace io_control
} // namespace detail
} // namespace asio
} // namespace boost
However, the code does not work.
If you have any example code or solution, please let me know.
Thank you.
When I create a D-Bus server (via g_bus_own_name()) and the client to it (using g_dbus_proxy_new()) in the same process and then call g_dbus_proxy_call_sync(), it never returns. However, if server and client are in separate processes, everything is ok.
The following code illustrates my problem (I am using giomm C++ bindings here):
file main.cc:
#include <giomm.h>
#include <thread>
int server_main();
int client_main();
int main() {
Gio::init();
std::thread thr_server([](){ server_main(); });
sleep(1); // give some time to server to register
std::thread thr_client([](){ client_main(); });
sleep(10); // wait for the client to finish
}
file server.cc:
#include <giomm.h>
#include <iostream>
namespace {
static Glib::RefPtr<Gio::DBus::NodeInfo> introspection_data;
static Glib::ustring introspection_xml =
"<node name='/org/glibmm/DBusExample'>"
" <interface name='org.glibmm.DBusExample'>"
" <method name='Method'>"
" </method>"
" </interface>"
"</node>";
guint registered_id = 0;
}
static void on_method_call(const Glib::RefPtr<Gio::DBus::Connection>& /* connection */,
const Glib::ustring& /* sender */, const Glib::ustring& /* object_path */,
const Glib::ustring& /* interface_name */, const Glib::ustring& method_name,
const Glib::VariantContainerBase& parameters,
const Glib::RefPtr<Gio::DBus::MethodInvocation>& invocation)
{
if(method_name == "Method") {
std::cout << "Method was called\n";
}
}
const Gio::DBus::InterfaceVTable interface_vtable(sigc::ptr_fun(&on_method_call));
void on_bus_acquired(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& /* name */)
{
std::cout << "on_bus_acquired\n";
try {
registered_id = connection->register_object("/org/glibmm/DBusExample",
introspection_data->lookup_interface(),
interface_vtable);
}
catch(const Glib::Error& ex) {
std::cerr << "Registration of object failed." << std::endl;
}
return;
}
void on_name_acquired(const Glib::RefPtr<Gio::DBus::Connection>& /* connection */, const Glib::ustring& /* name */)
{}
void on_name_lost(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& /* name */) {
connection->unregister_object(registered_id);
}
int server_main()
{
try {
introspection_data = Gio::DBus::NodeInfo::create_for_xml(introspection_xml);
}
catch(const Glib::Error& ex) {
std::cerr << "Unable to create introspection data: " << ex.what() <<
"." << std::endl;
return 1;
}
const guint id = Gio::DBus::own_name(Gio::DBus::BUS_TYPE_SESSION,
"org.glibmm.DBusExample",
sigc::ptr_fun(&on_bus_acquired),
sigc::ptr_fun(&on_name_acquired),
sigc::ptr_fun(&on_name_lost));
//Keep the service running
auto loop = Glib::MainLoop::create();
loop->run();
Gio::DBus::unown_name(id);
return EXIT_SUCCESS;
}
file client.cc:
#include <giomm.h>
#include <iostream>
Glib::RefPtr<Glib::MainLoop> loop;
// A main loop idle callback to quit when the main loop is idle.
bool on_main_loop_idle() {
std::cout << "loop_idle\n";
loop->quit();
return false;
}
void on_dbus_proxy_available(Glib::RefPtr<Gio::AsyncResult>& result)
{
auto proxy = Gio::DBus::Proxy::create_finish(result);
if(!proxy) {
std::cerr << "The proxy to the user's session bus was not successfully "
"created." << std::endl;
loop->quit();
return;
}
try {
std::cout << "Calling...\n";
proxy->call_sync("Method");
std::cout << "It works!\n";
}
catch(const Glib::Error& error) {
std::cerr << "Got an error: '" << error.what() << "'." << std::endl;
}
// Connect an idle callback to the main loop to quit when the main loop is
// idle now that the method call is finished.
Glib::signal_idle().connect(sigc::ptr_fun(&on_main_loop_idle));
}
int client_main() {
loop = Glib::MainLoop::create();
auto connection =
Gio::DBus::Connection::get_sync(Gio::DBus::BUS_TYPE_SESSION);
if(!connection) {
std::cerr << "The user's session bus is not available." << std::endl;
return 1;
}
// Create the proxy to the bus asynchronously.
Gio::DBus::Proxy::create(connection, "org.glibmm.DBusExample",
"/org/glibmm/DBusExample", "org.glibmm.DBusExample",
sigc::ptr_fun(&on_dbus_proxy_available));
loop->run();
return EXIT_SUCCESS;
}
I compile the test with g++ -O2 -std=c++0x main.cc server.cc client.cc -o test $(pkg-config --cflags --libs giomm-2.4) and run:
./test
on_bus_acquired
Calling...
<it hangs>
However, when I change main.cc:
#include <giomm.h>
int server_main();
int client_main();
int main() {
Gio::init();
auto childid = fork();
if (childid == 0) {
server_main();
} else {
sleep(1);
client_main();
}
}
I get:
./test
on_bus_acquired
Calling...
Method was called
It works!
So call_sync() returns successfully.
I tried to exclude loops from server and client, and use a single-threaded main.cc:
#include <giomm.h>
#include <thread>
int server_main();
int client_main();
int main() {
Gio::init();
server_main();
client_main();
auto loop = Glib::MainLoop::create();
loop->run();
}
Nothing helps. The question is, what am I doing wrong? I want to use my d-bus server and client in one process.
I figured it out, the trick is to execute
Glib::VariantContainerBase result;
invocation->return_value(result);
in the end of on_method_call.
In the following code, I'm having some sort of issue getting my .yaml file parsed using parser.GetNextDocument(doc);. After much gross debugging, I've found that the (main) issue here is that my for loop is not running, due to doc.size() == 0; What am I doing wrong?
void
BookView::load()
{
aBook.clear();
QString fileName =
QFileDialog::getOpenFileName(this, tr("Load Address Book"),
"", tr("Address Book (*.yaml);;All Files (*)"));
if(fileName.isEmpty())
{
return;
}
else
{
try
{
std::ifstream fin(fileName.toStdString().c_str());
YAML::Parser parser(fin);
YAML::Node doc;
std::map< std::string, std::string > entry;
parser.GetNextDocument(doc);
std::cout << doc.size();
for( YAML::Iterator it = doc.begin(); it != doc.end(); it++ )
{
*it >> entry;
aBook.push_back(entry);
}
}
catch(YAML::ParserException &e)
{
std::cout << "YAML Exception caught: "
<< e.what()
<< std::endl;
}
}
updateLayout( Navigating );
}
The .yaml file being read was generated using yaml-cpp, so I assume it is correctly formed YAML, but just in case, here's the file anyways.
^#^#^#\230---
-
address: ******************
comment: None.
email: andrew(dot)levenson(at)gmail(dot)com
name: Andrew Levenson
phone: **********^#
Edit: By request, the emitting code:
void
BookView::save()
{
QString fileName =
QFileDialog::getSaveFileName(this, tr("Save Address Book"), "",
tr("Address Book (*.yaml);;All Files (*)"));
if (fileName.isEmpty())
{
return;
}
else
{
QFile file(fileName);
if(!file.open(QIODevice::WriteOnly))
{
QMessageBox::information(this, tr("Unable to open file"),
file.errorString());
return;
}
std::vector< std::map< std::string, std::string > >::iterator itr;
std::map< std::string, std::string >::iterator mItr;
YAML::Emitter yaml;
yaml << YAML::BeginSeq;
for( itr = aBook.begin(); itr < aBook.end(); itr++ )
{
yaml << YAML::BeginMap;
for( mItr = (*itr).begin(); mItr != (*itr).end(); mItr++ )
{
yaml << YAML::Key << (*mItr).first << YAML::Value << (*mItr).second;
}
yaml << YAML::EndMap;
}
yaml << YAML::EndSeq;
QDataStream out(&file);
out.setVersion(QDataStream::Qt_4_5);
out << yaml.c_str();
}
}
Along the lines of what you thought, the problem is that you're writing using QDataStream but reading using plain std::ifstream. You need to do either one or the other.
If you want to use the QDataStream, you'll need to read it in as well. Check out the doc for more detail, but it looks like you can just grab the YAML string:
QDataStream in(&file);
QString str;
in >> str;
and then pass it to yaml-cpp:
std::stringstream stream; // remember to include <sstream>
stream << str; // or str.toStdString() - I'm not sure about how QString works
YAML::Parser parser(stream);
// etc.
The point of a std::stringstream is to transform your string containing YAML into a stream that the YAML parser can read.