i wrote a program for a pic32mx575f512h in C++. the processor has 6 uarts and the program routes the uart packets from one to another. the program is written using two generic classes. a receive class and a send class. when the objects for these classes are declared a struct with settings is handed to them to make them unique.
to ease interconnecting these objects the receive class is handed an array of send class pointers. when a message arrives say for uart "one" on any of the other uarts the receive class calls the appropriate send class from the array by using the address as the array index. for example:
send_pointer[received_address]->data_put()...
the code is tested and works well.
now i need to expand the code further to add debugging through usb. the usb stack is taken care of i just need a way to pass data from the receive class to the send class including a function for the usb. where i'm struggling is that the usb send handler is completely different from the the uart send class. i would like to add another member to the array of send pointers but that's not possible. i've tried making an array of function pointers but C++ won't allow storing the member of a class in a function pointer.
is there another way i can do this so i can still use the address as an index of where the message needs to go?
In order to execute methods of a class, you either need an instance, or the method has to be declared as static.
Search the internet for "c++ FAQ pointer to member function".
You may need to redesign you program or use a Factory Design pattern.
Related
Coming from mostly C#, I am going through the exercise of understanding how best to manage object ownership in c++, so bear with me.
I have a Bus class which has a method called OpenChannel that returns a Channel object. The Bus keeps a list of channels, because if the Bus is closed, all channels should be closed. If an individual channel is closed, the bus remains open, but the channel should be removed from the Bus open channel list.
The way I planned on handling this was as follows:
std::unique_ptr<Channel> Bus::OpenChannel(int channel_number){
int handle = //call dll to open channel
auto chnl = std::make_unique<Channel>(this, channel_number, handle);
this->open_channels_.push_back(chnl);
}
void Bus::OnChannelClosed(Channel channel){
//remove from open_channels_
}
and then in the channel class, there is a close method
void Channel::Close(){
//make call to dll to close channel
owning_bus_->OnChannelClosed(channel);
}
What I'm wondering is two fold -- first, for the bus being passed to the channel object's constructor, should I just use a regular pointer, or should I use a smart pointer? If a smart pointer, does it make sense to wrap "this" up in one? And two, it doesn't quite sit right with me that the bus has a public OnChannelClosed method that is exposed for any object to call. This could result in the Bus removing the channel due to a call from a non-channel object. I could make the Channel a friend of the Bus class, but my gut feel is there may be a better way.
edit:
based on some responses I figured I'd add more info. "Bus" wraps up a dll which can be initialized and uninitialized (and reinitialized again if required). When it is uninitialized, all open channel handles go invalid per the docs. I am starting to think my library wrapper should have an Initialize, Uninitialize, and "CreateChannel" method which returns a Channel which can then be operated on. Theoretically, I will never be uninitializing the bus while channels are open. But should it happen, I was hoping to gracefully manage that. However, if I'm exposing channel, there is a of course the possibility the channel object being used in another location goes invalid if the bus is uninitialized.
I think that the best way to handle this if possible is not allow the bus to be uninitialized as long as there are open channels. Maybe a shared pointer can be used to manage this? Or maybe channel shouldn't be exposed at all and Bus methods should all take a channel number as an input, and then the calls will be delegated to the correct channel.
With regards to your first question:
What I'm wondering is two fold -- first, for the bus being passed to
the channel object's constructor, should I just use a regular pointer,
or should I use a smart pointer?
Smart pointers are incredibly useful because they remove the need for manual memory tracking. In the example you provided, your Bus class only needs a pointer to a Channel so it can keep track of which Channel instance contains it. In this context, there is no need to use a smart pointer, since all bus instances should be destroyed before the channel that holds them.
And two, it doesn't quite sit right with me that the bus has a public
OnChannelClosed method that is exposed for any object to call.
If all that you're concerned is that no other class other than Bus should be able to invoke the method OnChannelClosed, you can always make Bus a friend class of Channel, and set the method OnChannelClosed as private or protected.
It feels however, that you are trying to manage memory with two different approaches here, though:
1- You want Channel to keep track of all Bus instances, and
2- You want to use smart pointer so you don't need to keep track of memory at all.
One thing I noticed is that Bus::OpenChannel stores a unique_ptr inside a vector, and, (presumably) returns that same unique_ptr as the output of the function. This is not possible. As the name suggests, unique pointers can only be owned by one object. If you need multiple objects to have access to the pointer, you should use a shared_ptr instead.
My question is probably just a simple question about using the c++ language, but the background/motivation involves networking code, so I'll include it
Background:
I have an application with a bunch of balls moving around according to various rules. There is a server and a client that should be as synchronized as possible about the state of each ball.
I'm using Google's Protocol Buffers to create message objects that allow the client to set up or update each ball. Balls have different states, and each ball might need to be transmitted to the client using a different message class generated by GPB. For example, one type of ball updates its position using a fixed acceleration vector, so the message corresponding to that type of ball would have position,velocity, and acceleration.
I want to store these message objects in a data structure that organizes them by position, so that clients can access only message objects that are nearby. But each message has a different class type, so I don't know how to correctly put them all in a structure.
If I were hand-writing the message classes, I would make them all be subclasses of an abstract Message base object, with an enum type member. Then I would store the messages as unique_ptrs to the abstract class and then do a static cast by the type enum whenever I needed to work with each object individually. Ideally, since I need to serialize the message objects (they each have a serializeToOutputStream(..)) function, I would make this function an abstract member of the base class and have each of the particular message classes override it, so that I could avoid a cast in some situations.
The problem is that I am not hand-writing these classes. They are generated by google's compiler. I'm sure such a situation has arisen before, so I wonder how I should deal with it in an elegant way, if there is one.
Language-Only Version of Question:
I have a fixed set of generated classes A,B,C,D... that all have a few common functions like serializeToStream(). It would be very tedious to alter these classes since their sources are generated by a compiler. I would like to store unique pointers or raw pointers to these objects in a data structure of some kind, like an std::map or std::vector, but I don't know how to do this. If possible it would be great to call some of the functions that they all have without knowing which particular class I was dealing with (such as if I call the serialize function on all of them in a vector).
There is not good way to solve your problem. Only nasty haks. For example you can store pointer to object and pointer to method of some fake type in your map. But then you must cast your classes and pointers of its methods by reinterpret to this fake type. You must remember that all who will read that your code will scold you and may be better to find the approach to create common base.
I have a situation where I have an object of a class in C++, which needs to be send across process boundaries (process 1 to process 2) using Linux pipes. I searched online on how to do serialization in C++. I found boost, but it requires some changes in the class. In my situation I cannot change the class.
This class has a lot of pointers, and the nesting continues to 3 levels (Class 1 has pointer 1 of type Class 2-> Class 2 has pointer 2 of type Class 3 -> Class 3 has pointer 3 of type class 4 -> Class 4). Is there any way I can send this object using pipes so that it can be recreated in the second process ?
Thanks.
You'll need to serialize the class somehow. How exactly is your choice, but you can do so in a format like JSON, or XML, or some kind of binary format you decide on. Without seeing any more details on your class, there's not much else to add.
Another option might be to use Shared memory segments to store the class, but that comes with issues with pointer math, concurrency and other complications.
Have you considered an application of the Memento pattern? You could create a class or classes to handle the details of how to serialize the object (either to text or binary).
The class you create to save objects would also know how to instantiate new objects from the serialization format you choose in the next process.
You're going to have to do some sort of serialization, because you can't copy-construct across a pipe or anything like that. If you can't change the class then your only choice is to write an external function or class that uses your top level class's public API to get all the pieces and serialize that data. Then on the other end you'll have to reconstruct it from the stream.
I am just getting back into programming, so forgive me if this is very silly.
I have 2 classes (for now). One is the Windows Form class, where I am using a Button_Click event to trigger a communication port opening. I want to pass data that the user entered on the form on to the Communication class for further processing (sending).
This is the part that initializes and calls the Communication class:
wchar_t * data = new wchar_t[nLength];
*data = *wch;
SerialCommunication comm1;
bool comm1ok = comm1.SerialWrite(data);
Variable "data" is a pointer, so I want to pass its address to the other class to use.
This is my 2nd class:
bool SerialCommunication::SerialWrite(wchar_t * datar){...
But the data never makes it there. It goes out of scope as soon as the SerialWrite() function starts up. Do I need to declare this pointer in some other way to make sure it doesn't disappear when I move between classes?
The classes are both public, as far as I know (well, I wrote the SerialCommunication one, so I know it's public).
What am I doing wrong? What should I change?
Thanks!
This:
*data = *wch;
does not do what you think (or what I assume you think). It just copies the first element of wch into the first element of data.
two clients communicate to each other on top of a message layer
in the message body, I need include a field pointing to any data type
From client A, I send the field as a shared_ptr<TYPEA> to the message layer.
I define this field as a shared_ptr<void> in the message layer.
But how can I convert this field back to shared_ptr<TYPEA> in client B?
Or should I define shared_ptr<void> in message layer as something else?
Thanks
If you're using boost::shared_ptr then you can use the various XXX_ptr_cast<>() functions (static_ptr_cast, dynamic_ptr_cast...).
If you're using the MSVC 2010 version I haven't been able to find an implementation of these functions. They may not be part of the standard.
If the shared_ptrs & pointed-to data aren't held in memory common to both clients (e.g. the clients run in different processes, and the data isn't in shared memory), the pointers from one client won't be valid for the other. You'll need to construct a representation of the pointed-to data and transmit that. The receiver constructs its own copy of the data in the messaging layer and passes a shared_ptr to that up to the client.
If all possible data types that you plan on passing between clients inherit from some common base class, you can simply include a flag variable in the base class which indicates which derived type the current instance is. Pass base-class pointers between clients, and then use dynamic_cast to downcast the base pointer to the appropriate derived type.