I'm trying to use boost library 1.55.0 to create a shared memory.I have a example.cpp file which creates boost shared memory. Mexing of this file is successful,but throws the following exception while debugging "MATLAB.exe has triggered a breakpoint".Is this exception because of the version of the boost being incompatible with the matlab version? How to resolve this
`/* File : sfun_counter_cpp.cpp
* Abstract:
*
* Example of an C++ S-function which stores an C++ object in
* the pointers vector PWork.
*
* Copyright 1990-2000 The MathWorks, Inc.
*
*/
#include "iostream"
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
typedef struct
{
int outGate;
unsigned int outPin;
int inGate;
unsigned int inPin;
} wire;
typedef struct
{
unsigned int gateType;
unsigned int inPins;
unsigned int outPins;
std::vector<wire> inWires;
std::vector<wire> outWires;
} gate;
std::vector<gate> gates;
wire wiredata;
gate gatedata;
class counter {
double x;
public:
counter() {
x = 0.0;
}
double output(void) {
x = x + 1.0;
return x;
}
};
#ifdef __cplusplus
extern "C" { // use the C fcn-call standard for all functions
#endif // defined within this scope
#define S_FUNCTION_LEVEL 2
#define S_FUNCTION_NAME sfun_counter_cpp
/*
* Need to include simstruc.h for the definition of the SimStruct and
* its associated macro definitions.
*/
#include "simstruc.h"
/*====================*
* S-function methods *
*====================*/
/* Function: mdlInitializeSizes ===============================================
* Abstract:
* The sizes information is used by Simulink to determine the S-function
* block's characteristics (number of inputs, outputs, states, etc.).
*/
static void mdlInitializeSizes(SimStruct *S)
{
/* See sfuntmpl_doc.c for more details on the macros below */
ssSetNumSFcnParams(S, 1); /* Number of expected parameters */
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
/* Return if number of expected != number of actual parameters */
return;
}
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
if (!ssSetNumInputPorts(S, 0)) return;
if (!ssSetNumOutputPorts(S, 1)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 1); // reserve element in the pointers vector
ssSetNumModes(S, 0); // to store a C++ object
ssSetNumNonsampledZCs(S, 0);
ssSetOptions(S, 0);
}
/* Function: mdlInitializeSampleTimes
=========================================
* Abstract:
* This function is used to specify the sample time(s) for your
* S-function. You must register the same number of sample times as
* specified in ssSetNumSampleTimes.
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, mxGetScalar(ssGetSFcnParam(S, 0)));
ssSetOffsetTime(S, 0, 0.0);
}
#define MDL_START /* Change to #undef to remove function */
#if defined(MDL_START)
/* Function: mdlStart
=======================================================
* Abstract:
* This function is called once at start of model execution. If you
* have states that should be initialized once, this is the place
* to do it.
*/
static void mdlStart(SimStruct *S)
{
ssGetPWork(S)[0] = (void *) new counter; // store new C++ object in
the
} // pointers vector
#endif /* MDL_START */
/* Function: mdlOutputs =======================================================
* Abstract:
* In this function, you compute the outputs of your S-function
* block. Generally outputs are placed in the output vector, ssGetY(S).
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
using namespace boost::interprocess;
counter *c = (counter *) ssGetPWork(S)[0]; // retrieve C++ object from
shared_memory_object::remove("MySharedMemory");
//create the shared memory
managed_shared_memory segment(create_only, "MySharedMemory", 65536);
//create the allocators for the struct elements to be accessed as
vectors
typedef allocator<gate,
managed_shared_memory::segment_manager>gate_alloc;
typedef allocator<wire,
managed_shared_memory::segment_manager>inwire_alloc;
typedef allocator<wire,
managed_shared_memory::segment_manager>outwire_alloc;
//create a boost vector with an associated allocator to it
typedef vector<gate, gate_alloc>gate_vec;
typedef vector<wire, inwire_alloc>inwire_vec;
typedef vector<wire, outwire_alloc>outwire_vec;
//Initialize shared memory STL-compatible allocator
const gate_alloc alloc_inst(segment.get_segment_manager());
const inwire_alloc alloc_inst1(segment.get_segment_manager());
const outwire_alloc alloc_inst2(segment.get_segment_manager());
//construct the segment for pushing the data into it
gate_vec *gate_data = segment.construct<gate_vec>("gatedata")
(alloc_inst);
inwire_vec *inwire_data = segment.construct<inwire_vec>("inwiredata")
(alloc_inst1);
outwire_vec *outwire_data = segment.construct<outwire_vec>
("outwiredata")
(alloc_inst2);
//push the data into the vectors
wiredata.inGate = 10;
wiredata.inPin = 2;
wiredata.outGate = 1;
wiredata.outPin = 3;
inwire_data->push_back(wiredata);
outwire_data->push_back(wiredata);
gatedata.gateType = 1;
gatedata.inPins = 2;
gatedata.outPins = 3;
gate_data->push_back(gatedata);
real_T *y = ssGetOutputPortRealSignal(S,0); // the pointers vector
and use
y[0] = c->output(); // member functions of
the
} // object
/* Function: mdlTerminate
=====================================================
* Abstract:
* In this function, you should perform any actions that are necessary
* at the termination of a simulation. For example, if memory was
* allocated in mdlStart, this is the place to free it.
*/
static void mdlTerminate(SimStruct *S)
{
counter *c = (counter *) ssGetPWork(S)[0]; // retrieve and destroy C++
delete c; // object in the
termination
} // function
/*======================================================*
* See sfuntmpl_doc.c for the optional S-function methods *
*======================================================*/
/*=============================*
* Required S-function trailer *
*=============================*/
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file?*/
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif
#ifdef __cplusplus
} // end of extern "C" scope
#endif
`
this is the sfunction which I have to mex , debug and run .Though the mexing of the above code snippet is successful ,it throws an exception "MATLAB.exe has triggered a breakpoint" while debugging.
I can give you an example. Unfortunately I cannot test it with windows, but I have tested it on a UNIX system. The main idea is the same. In this case it is shared memory from an external binary to a Matlab mex function.
The external binary is:
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
using namespace boost::interprocess;
const std::string payload("SHARED MEMORY CONTENT");
int main(void) {
shared_memory_object shm(open_or_create, "memory4mat" ,read_write);
shm.truncate(payload.size());
mapped_region mem(shm, read_write);
std::memcpy(mem.get_address(), payload.c_str(), mem.get_size());
do {
std::cout << '\n' << "Press a key to continue...";
} while (std::cin.get() != '\n');
shared_memory_object::remove("memory4mat");
return 0;
}
while the mex function is:
#include "mex.hpp"
#include "mexAdapter.hpp"
#include "MatlabDataArray.hpp"
#include <string>
#include <cstdlib>
#include "boost/interprocess/shared_memory_object.hpp"
#include "boost/interprocess/mapped_region.hpp"
using namespace boost::interprocess;
class MexFunction : public matlab::mex::Function {
public:
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
matlab::data::ArrayFactory factory;
shared_memory_object shm(open_only, "memory4mat", read_only);
mapped_region mem(shm, read_only);
std::string payload(static_cast<const char *>(mem.get_address()), mem.get_size());
outputs[0] = factory.createCharArray(payload);
outputs[1] = factory.createScalar<int16_t>(mem.get_size());
}
};
it uses the C++ Interface and Data API for Matlab. To compile the two example you need to add the boost include directory as compiler options (shared memory is a header only feature in boost).
The external binary create a shared memory that contains the string "SHARED MEMORY CONTENT", and waits an enter from the user to remove the shared memory object.
The mex files opens the shared memory if exist (if the shared memory do not exist an error is reported and handled in Matlab, which is one of the reasons why I prefer C++ api) and copy its content in a Matlab char array. The function returns two values, the first is the content of the shared memory, the second is the length of the shared memory (the mapper uses all the memory, set with truncate).
This simple example uses only basic features and should work on Unix and Windows system, but again I cannot test on win.
A more complete example
Let's try with a more complete example about shared memories and Matlab Mex files. Let us write a very simple external binary that allows us to create/delete/read/write a shared memory. This binary has a lot of stuff hardcoded for simplicity, such as the name of the memory file ("shmem"):
// File: share_server.cpp
// g++ share_server.cpp -o share_server
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
using namespace boost::interprocess;
static const std::size_t size = 20;
static const std::size_t wsize = 15;
static const char name[6] = "shmem";
static const char input[wsize] = "write in share";
char output[size];
inline void printHelp() {
std::cout << "Options:" << std::endl;
std::cout << " n) open a new 'shmem' memory" << std::endl;
std::cout << " d) delete a 'shmem' memory" << std::endl;
std::cout << " r) read from 'shmem' memory" << std::endl;
std::cout << " w) write to 'shmem' memory" << std::endl;
std::cout << " x) Exit" << std::endl;
}
inline void cmd_createShare() {
try {
shared_memory_object sm(create_only, name, read_write);
sm.truncate(size);
std::cout << "Shared object created" << std::endl;
} catch(std::exception & e) {
std::cout << "Create Error :: " << e.what() << std::endl;
}
}
inline void cmd_deleteShare() {
try {
shared_memory_object::remove(name);
std::cout << "Shared object deletetd" << std::endl;
} catch(std::exception & e) {
std::cout << "Delete Error:: " << e.what() << std::endl;
}
}
inline void cmd_readShare() {
try {
shared_memory_object sm(open_only, name, read_only);
mapped_region sh_mem(sm, read_only);
std::string ret(static_cast<const char *>(sh_mem.get_address()), sh_mem.get_size());
std::cout << ret << std::endl;
} catch(std::exception & e) {
std::cout << "Read Error:: " << e.what() << std::endl;
}
}
inline void cmd_writeShare() {
try {
shared_memory_object sm(open_only, name, read_write);
mapped_region sh_mem(sm, read_write);
std::memcpy(sh_mem.get_address(), input, wsize);
std::cout << "Write completed" << std::endl;
} catch(std::exception & e) {
std::cout << "Read Error:: " << e.what() << std::endl;
}
}
we can write 3 mex files (using the C++ api) in order to interact with the shared memory. The first one, the simplest, reads the content of the shared memory as a string and returns it to the Matlab workspace. The interface in Matlab syntax is something like:
function [value, read_size] = read_share(share_name)
...
end
and the C++ implementation is the following:
// File: read_share.cpp
#include "mex.hpp"
#include "mexAdapter.hpp"
#include "MatlabDataArray.hpp"
#include <string>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <exception>
#include "boost/interprocess/shared_memory_object.hpp"
#include "boost/interprocess/mapped_region.hpp"
using namespace boost::interprocess;
using namespace matlab::data;
class MexFunction : public matlab::mex::Function {
private:
std::shared_ptr<matlab::engine::MATLABEngine> engine;
ArrayFactory factory;
void throwError(std::string errorMessage) {
engine->feval(matlab::engine::convertUTF8StringToUTF16String("error"),
0, std::vector<Array>({ factory.createScalar(errorMessage) }));
}
uint64_t read_shared_memory(const std::string & name, std::string & ret_value) {
try {
shared_memory_object sm(open_only, name.c_str(), read_only);
mapped_region sh_mem(sm, read_only);
ret_value += std::string(static_cast<const char *>(sh_mem.get_address()), sh_mem.get_size());
return ret_value.size();
} catch(std::exception & e) {
throwError(std::string("Reading error: ") + std::string(e.what()));
}
return 0;
}
void checkArguments(matlab::mex::ArgumentList inputs, matlab::mex::ArgumentList outputs) {
if (inputs.size() != 1)
throwError("Input must be of size 1");
if (inputs[0].getType() != ArrayType::CHAR)
throwError("First element must be a matlab char array");
if (outputs.size() > 2)
throwError("Too many outputs (required 1)");
}
public:
MexFunction() {
engine = getEngine();
}
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
checkArguments(inputs, outputs);
const CharArray name_array = std::move(inputs[0]);
std::string name = name_array.toAscii();
std::string ret_string("");
uint64_t ret_size = read_shared_memory(name, ret_string);
outputs[0] = factory.createScalar(ret_string);
outputs[1] = factory.createScalar<uint64_t>(ret_size);
}
};
The second mex file is the write operation. It takes two input: the name of the shared memory and the string to write inside the memory. The mex checks the maximum size of the shared memory and stores no more than the available space. The function returns the bytes written in the The interface for the write function is something like:
function written_size = write_share(share_name, string)
...
end
and the implementation is:
// File: write_share.cpp
#include "mex.hpp"
#include "mexAdapter.hpp"
#include "MatlabDataArray.hpp"
#include <string>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <exception>
#include "boost/interprocess/shared_memory_object.hpp"
#include "boost/interprocess/mapped_region.hpp"
using namespace boost::interprocess;
using namespace matlab::data;
class MexFunction : public matlab::mex::Function {
private:
std::shared_ptr<matlab::engine::MATLABEngine> engine;
ArrayFactory factory;
void throwError(std::string errorMessage) {
engine->feval(matlab::engine::convertUTF8StringToUTF16String("error"),
0, std::vector<Array>({ factory.createScalar(errorMessage) }));
}
uint64_t write_shared_memory(const std::string & name, const std::string & value) {
try {
shared_memory_object sm(open_only, name.c_str(), read_write);
mapped_region sh_mem(sm, read_write);
uint64_t size = std::min(value.size(), sh_mem.get_size());
std::memcpy(sh_mem.get_address(), value.c_str(), size);
return size;
} catch(std::exception & e) {
throwError(std::string("Reading error: ") + std::string(e.what()));
}
return 0;
}
void checkArguments(matlab::mex::ArgumentList inputs, matlab::mex::ArgumentList outputs) {
if (inputs.size() != 2)
throwError("Input must be of size 2");
if (inputs[0].getType() != ArrayType::CHAR)
throwError("First element must be a matlab char array");
if (inputs[1].getType() != ArrayType::CHAR)
throwError("Second element must be a matlab char array to save");
if (outputs.size() > 1)
throwError("Too many outputs (required 1)");
}
public:
MexFunction() {
engine = getEngine();
}
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
checkArguments(inputs, outputs);
const CharArray name_array = std::move(inputs[0]);
std::string name = name_array.toAscii();
const CharArray value_array = std::move(inputs[1]);
std::string value = value_array.toAscii();
uint64_t written = write_shared_memory(name, value);
outputs[0] = factory.createScalar<uint64_t>(written);
}
};
The last mex is the most complex and handles the creation and deletion of the shared memory. You will notice the presence of a destructor that handles the removal of shared memory when the mex is unloaded from Matlab. The interface takes a command in the form of "create" or "delete", a string with the name of the share and the size of the shared memory for creation (it must be an unsigned int - uint16(...)). The function returns the size of the shared memory (it should be equal to size):
function size_shmem = menage_mex(command, share_name, uint16(size))
...
end
the implementation is the following:
// File: menage_share.cpp
#include "mex.hpp"
#include "mexAdapter.hpp"
#include "MatlabDataArray.hpp"
#include <string>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <exception>
#include "boost/interprocess/shared_memory_object.hpp"
#include "boost/interprocess/mapped_region.hpp"
using namespace boost::interprocess;
using namespace matlab::data;
class MexFunction : public matlab::mex::Function {
private:
std::shared_ptr<matlab::engine::MATLABEngine> engine;
ArrayFactory factory;
std::vector<std::string> pool;
void throwError(std::string errorMessage) {
engine->feval(matlab::engine::convertUTF8StringToUTF16String("error"),
0, std::vector<Array>({ factory.createScalar(errorMessage) }));
}
uint64_t run_command(const std::string & cmd, const std::string & name, uint64_t size) {
if (cmd == "create")
return create_shared_memory(name, size);
if (cmd == "delete")
return delete_shared_memory(name, size);
throwError("The command is unknown");
return 0;
}
uint64_t create_shared_memory(const std::string & name, uint64_t size) {
bool in_pool = false;
for (const auto & el : pool) {
if (el == name) {
in_pool = true;
break;
}
}
if (in_pool) {
try {
shared_memory_object sm(open_only, name.c_str(), read_only);
mapped_region sm_reg(sm, read_only);
if (sm_reg.get_size() != size)
throwError("Memory already exist and it is of different size");
return 0;
} catch (std::exception & e) {
throwError(std::string("Cannot open existing shared memory (maybe already open?) :: ") + std::string(e.what()));
}
} else {
try {
shared_memory_object sm(create_only, name.c_str(), read_write);
sm.truncate(size);
pool.push_back(name);
return size;
} catch (std::exception & e) {
throwError(std::string("Cannot create shared memory [" + name + "] (maybe already open?) :: ") + std::string(e.what()));
}
}
return 0;
}
uint64_t delete_shared_memory(const std::string & name, uint64_t size) {
std::size_t in_pool = 0;
for (const auto & el : pool) {
if (el == name)
break;
in_pool++;
}
if (in_pool < pool.size()) {
shared_memory_object::remove(name.c_str());
pool.erase(pool.begin() + in_pool);
} else {
throwError("Shared memory [" + name + "] is not handled by this mex");
}
return 0;
}
void checkArguments(matlab::mex::ArgumentList inputs, matlab::mex::ArgumentList outputs) {
if (inputs.size() != 3)
throwError("Input must be of size 3");
if (inputs[0].getType() != ArrayType::CHAR)
throwError("First element must be a matlab char array");
if (inputs[1].getType() != ArrayType::CHAR)
throwError("Second element must be amatlab char array");
if (inputs[2].getType() != ArrayType::UINT64)
throwError("Third element must be a single uint64 integer");
if (outputs.size() > 1)
throwError("Too many outputs (required 1)");
}
void inputArguments(std::string & cmd, std::string & name, uint64_t & size, matlab::mex::ArgumentList inputs) {
const CharArray cmd_array = std::move(inputs[0]);
const CharArray name_array = std::move(inputs[1]);
const TypedArray<uint64_t> size_array = std::move(inputs[2]);
cmd = cmd_array.toAscii();
name = name_array.toAscii();
size = size_array[0];
}
public:
MexFunction() {
pool.clear();
engine = getEngine();
}
~MexFunction() {
for (const auto & el : pool) {
shared_memory_object::remove(el.c_str());
}
}
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
checkArguments(inputs, outputs);
std::string cmd, name;
uint64_t size;
inputArguments(cmd, name, size, inputs);
uint64_t ret = run_command(cmd, name, size);
outputs[0] = factory.createScalar<uint64_t>(ret);
}
};
To compile the mex you can use the following script:
MEX_OPT = ['-I', '/path/to/boost'];
MEX_SRC = { ...
'menage_share.cpp', ...
'read_share.cpp', ...
'write_share.cpp' ...
};
for i = 1:length(MEX_SRC)
mex(MEX_OPT, MEX_SRC{i});
end
!g++ share_server.cpp -o share_server
and you can test them as follows:
(MATLAB) | (TERMINAL)
>> menage_share('create', 'shmem', uint64(20)) |
<< 20 |
>> write_share('shmem', 'Hello there') | $ ./share_server
<< 11 | ( ... help message ... )
| << r
| >> Hello there
I am trying to learn how to use priority_queue vs queue. I have this code for a priority_queue that's supposed to get input from users. The input is a chore and the priority number of the chore. They can enter as many as they want and it's supposed to output them in order. My problem is that it's not outputting them in order. I'm not sure if it's in my main or in my overloaded < operator function. Here is my Chore.h code:
#include<iostream>
#include<fstream>
using namespace std;
//#ifndef CHORE_H;
//#define CHORE_H;
class Chore{
public:
Chore(){priorityNum=0;choreName="";}
std::string getName (Chore c1)const{return choreName;}
int getPriorityNum(Chore c1)const{return priorityNum;}
bool operator <(const Chore c1)const;
std::ostream& output(std::ostream& cout,const Chore c)const;
std::istream& input(std::istream& cin);
private:
std::string choreName;
int priorityNum;
};
//#endif
Here's my Chore.cc code:
#include"Chore.h"
using namespace std;
bool Chore::operator <(const Chore c1)const{
Chore c2;
int c1Num=c1.getPriorityNum(c1);
int c2Num=c2.getPriorityNum(c2);
return c1Num<c2Num;
/*if(c1Num<c2Num)
return true;
else if(c1Num==c2Num)
return true;
else
return false;*/
}
std::ostream& Chore::output(std::ostream& cout,const Chore c)const{
cout<<endl<<"Chore: "<<getName(c)<<endl;
cout<<"chore Priority: "<<getPriorityNum(c);
}
std::istream& Chore::input(std::istream& cin){
cout<<endl<< "Enter chore name:";
cin >>choreName;
cout<<endl<<"Enter priority number:";
cin >>priorityNum;
}
my main is below:
#include<queue>
#include<iostream>
#include"Chore.h"
using namespace std;
int main(){
std::priority_queue<Chore>myChores;
Chore tmp;
bool enterAnother=true;
//input loop
while(enterAnother){
char c;//checks if they want to continue
tmp.input(cin);
myChores.push(tmp);
cout<<endl<<"Want to enter another chore?(y for yes, n for no)";
cin >>c;
if(c=='y'|| c=='Y')
enterAnother=true;
else
enterAnother=false;
}
//output loop
while(!myChores.empty()){
tmp = myChores.top();
myChores.top().output(cout,tmp);
myChores.pop();
}
}
Any help would be greatly appreciated.
All I do is construct a BNode object. The debugger says that the constructor is causing a segmentation fault. Does anyone know what the problem is here?
All I do is construct a BNode object. The debugger says that the constructor is causing a segmentation fault. Does anyone know what the problem is here?
#ifndef BTree_H
#define BTree_H
#include <iostream>
#include <fstream>
#include <cctype>
#include <string>
#include <sstream>
#include <cmath>
using namespace std;
template <typename T>
class BNode
{
public:
BNode();
BNode(int M);
~BNode();
int keyCount;
BNode *pointers;
T *keys;
};
template<typename T>
BNode<T>::BNode()
{
}
template<typename T>
BNode<T>::BNode(int M)
{
pointers = new BNode<T>[M];
keys = new T[M - 1];
}
template<typename T>
BNode<T>::~BNode()
{
delete[] pointers;
delete[] keys;
}
#endif
int main()
{
BNode<int> obj(5);
return 0;
}
You are deleting an array of pointers and keys, whereas you never defined these to be arrays.
Both of these are pointers.
You need to be freeing memory from the pointers, not arrays.
Try this:-
delete myPointer;
myPointer = NULL;
NOTE: If you're using C++, read about smart pointers. They'll come in handy!
A smart pointer clears the memory if the pointer gets out of scope. I wanted to adapt this to a file descriptor, like a socket. There you need a user defined deleter, because close() is the function to free the file descriptor (fd) resources.
I found this useful page, unfortunately, most approaches did not work for me. Below is a working solution I found up to now, which is a little nasty. Because uniqu_ptr expects a pointer I created int *fd to store the fd value, therefore, I had to close(*fd) and delete fd in my custom deleter.
(1) Is there a better way?
Options A and B, which are based on the hints provided by the mentioned web page, are much nicer but causing odd compiler errors.
(2) Does anyone know how to correctly use these alternatives?
I'm using Qt Creator 3.0.1 with CONFIG += c++11 option and gcc version 4.8.2
#include "ccommhandler.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <memory>
#include <qdebug.h>
//for Option A and B
struct CloseHandleDeleter {
typedef int pointer;
void operator()(int handle) const
{
}
};
//custom deleter, working
class MyComplexDeleter
{
public:
MyComplexDeleter() {}
void operator()(int* ptr) const
{
qDebug() << "Deleting ";
close(*ptr);
delete ptr;
}
};
CCommHandler::CCommHandler()
{
//Option A doesn't work
//std::unique_ptr<int, CloseHandleDeleter> file( socket(AF_INET, SOCK_STREAM, 0) );
//Option B doesn't work
//std::unique_ptr<int, int()(int)> filePtr( socket(AF_INET, SOCK_STREAM, 0) , close);
MyComplexDeleter deleter;
int *fd = new int;
*fd = socket(AF_INET, SOCK_STREAM, 0);
std::unique_ptr<int, MyComplexDeleter> p( fd , deleter);
}
Edit:
The posted answer by Nevin is right, it solves my initial problem.
The comment of learnvst caused to rethink my problem, and I have to say I may made it much more complex than needed, because the following simple class should also solve my problem of auto-free the memory of a resource or as in my case, to close the file descriptor:
class SocketHandler
{
int _fd;
public:
SocketHandler(int FD):_fd(FD){}
~SocketHandler() { if(_fd!=-1) close(_fd); }
operator int() const { return _fd; }
};
Because fd isn't a pointer, I wouldn't try to pigeonhole it into unique_ptr. Instead, create a custom class whose interface is based on unique_ptr, as in (caution: totally untested):
class unique_fd
{
public:
constexpr unique_fd() noexcept = default;
explicit unique_fd(int fd) noexcept : fd_(fd) {}
unique_fd(unique_fd&& u) noexcept : fd_(u.fd_) { u.fd_ = -1; }
~unique_fd() { if (-1 != fd_) ::close(fd_); }
unique_fd& operator=(unique_fd&& u) noexcept { reset(u.release()); return *this; }
int get() const noexcept { return fd_; }
operator int() const noexcept { return fd_; }
int release() noexcept { int fd = fd_; fd_ = -1; return fd; }
void reset(int fd = -1) noexcept { unique_fd(fd).swap(*this); }
void swap(unique_fd& u) noexcept { std::swap(fd_, u.fd_); }
unique_fd(const unique_fd&) = delete;
unique_fd& operator=(const unique_fd&) = delete;
// in the global namespace to override ::close(int)
friend int close(unique_fd& u) noexcept { int closed = ::close(u.fd_); u.fd_ = -1; return closed; }
private:
int fd_ = -1;
};
I work on project based on a FASTRACK SUPREME which has to receive commands via a serial RS232. The
problem is:
When I use HyperTerm the command ATDxxxxxxxxx; works fine.
When I use the CVI RS232 library nothing happens. Is it possible that my command remains blocked in
the serial buffer?
Here is my code:
#include <ansi_c.h>
#include <cvirte.h>
#include <userint.h>
#include <rs232.h>
#include <utility.h>
#include <formatio.h>
#include <string.h>
int configurePort(void);
int sendCommand(void);
int port_open;
int error;
int main()
{
configurePort();
sendCommand ();
return 0;
}
int configurePort()
{
port_open = 0;
error = OpenComConfig (4, "COM4",115200 ,0,8,1,0, -1);
if (error)
{
printf("Error!\n");
}
if (error == 0)
{
port_open = 1;
SetXMode (4, 0);
SetCTSMode (4, 0);
SetComTime (4, 0);
}
return 0;
}
int sendCommand ()
{
char bufferWrite[100] ;
Fmt(bufferWrite,"%s","ATD0040761768027;");
ComWrt(4, bufferWrite, 18);
return 0;
}
Where is the problem? Please help!
Thanks.
I tried your code as it was. I am not sure what you mean by "nothing happens" When I used the code as it is (except I had to use port 2) everything worked well. the character count was 18 out of the ComWrt function.
Make sure the com port you are trying to use is available.
with the exception of your #includes, here is your code with minor mods that I ran on my PC, WinXP running CVI 2010:
#define PORT 2
#define PORTNAME "COM2"
int configurePort(void);
int sendCommand(void);
int port_open;
int error;
int main()
{
configurePort();
sendCommand ();
return 0;
}
int configurePort()
{
port_open = 0;
error = OpenComConfig (PORT, PORTNAME,115200 ,0,8,1,0, -1);
if (error)
{
printf("Error!\n");
}
if (error == 0)
{
port_open = 1;
SetXMode (PORT, 0);
SetCTSMode (PORT, 0);
SetComTime (PORT, 0);
}
return 0;
}
int sendCommand ()
{
char bufferWrite[100] ;
Fmt(bufferWrite,"%s","ATD0040761768027;");
error = ComWrt(PORT, bufferWrite, sizeof("ATD0040761768027;"));
return 0;
}