I am passing a callback function to a library. What the callback essentially does is receive updates from the dll and send it to GUI to display. The problem is that since the callback is global or static function, it doesn't know about the GUI and who to pass which in my case will be dialog. The approach I have used to accomplish this is to use singleton and a proxy (sort of).
class CDispatcher
{
public:
CDispatcher(void);
~CDispatcher(void);
protected:
static HWND m_hWnd;
public:
static void SetWindow( HWND hWnd );
static void Dispatch(int code, char * msg);
};
Later in the code
BOOL CTestDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// I need to set this before I set callback
CDispatcher::SetWindow( m_hWnd );
//now I can set the callback
LibRegisterCallback( CDispatcher::Dispatch );
return TRUE; // return TRUE unless you set the focus to a control
}
While this works but first I don't know if my CDispatcher class is good module. It doesn't seem like a good singleton neither it looks like a good proxy. Maybe I could pass the handle of the window in constructor which would make it better but I don't if that's even possible since I am never instantiating the singleton. Another thing is I never how to instantiate CDispatcher because again its just a all global members.
Is this a case where proxy design pattern can be applied in a better way (I am guessing in conjuction with singleton)? Maybe another pattern solves this problem more elegantly? Or is my implementation fine?
Related
I'm writing a Node application (in TS) that needs to be interfaced with some native library.
I have a library (written in C) - let's consider it's a blackbox - and I'm writing a wrapper using NAN. The library native interface can be simplified into a following functions:
typedef void (*got_message_reply_cb)(context ctx, void * priv, struct X * the_reply);
context lib_connect();
bool lib_send_message(context ctx, message msg, got_message_reply_cb callback, void * priv);
I believe this is pretty straight-forward to understand.
So, I'm trying to wrap that black-box native library into something like:
class TheLibrary : public Nan::ObjectWrap {
Initialize(v8::Handle<v8::Object> target);
SendMessage(...)
}
And then to javascript object like:
class TheLibrary {
SendMessage(message: whatever, callback: (reply) => void); // or return promise, doesn't matter
}
How to do the actual handling of the callback in the NAN C++ module? I need to somehow pass the callback (represented probably by Local<Function> - which have, if I understand it correctly, limited scope) as a pointer to the function and then retrieve it back. How to do that? Thanks for your replies.
The high level answer is that you don't pass the JS callback function directly, but pass in a pointer to a function that somehow has your JS callback as a context value (in your example the priv parameter).
So for your case you write something like this:
void TheLibraryCallback(context ctx, void *instance, struct X *the_reply) {
((TheLibrary*)instance)->callback(ctx, the_reply);
}
In your TheLibrary you add a method void callback(context ctx, struct X * the_reply) that handles the callback. You call your library like this: lib_send_message(ctx, msg, TheLibraryCallback, this); with this being a TheLibrary instance.
So how do you call back the JS callback in your callback method? With nan you will have to make sure you are back in the main thread. There are examples out there, but I would suggest that you use the new N-API instead. The AsyncWorker helps with the boilerplate that you need to do to call the callback in the main thread.
I am writing an audio rendering library that takes as input audio buffers, does some magic, then manage playback on a selected device. For this task, I decided to use Qt's QAudioOutput class.
I would like to allow the user to set callbacks when the state of the QAudioOutput object state changes (active, suspended, stopped and idle). I would connect these signals to a signal handler that would call the user-defined callbacks. However, I have the following restriction: no STL, no Qt, no Boost on the library header. I also need to stay compatible with C++98.
Right now, I have 2 solutions (with drawbacks) and I am looking to improve the design. My first solution was:
// library header
class AudioLibrary
{
typedef void ( *Callback )();
void setOnActiveCallback( Callback cb );
};
The problem with this solution is that the client can only pass static functions or non-capturing lambdas. This is too restrictive. Imagine a client who wants to do something as simple as re-enabling a button once playback finished. Not possible if the button is a member variable.
My second solution was that my interface would be an abstract class and contains pure virtual functions that would contain the desired behavior on state change. However, I am not sure this would be much fun for the client of the library...
Is there a cleaner and/or better solution that I ommited to think of?
This sounds like a C style callback.
class AudioLibrary
{
typedef void ( *Callback )( void * );
void setOnActiveCallback( Callback cb, void * context );
// Perhaps also include
template <typename Func>
void setOnActiveCallback( Func & f )
{
setOnActiveCallback( &Func::operator(), &f );
}
};
C-style callbacks without a means to pass context are completely utterly broken and your users will hate you for that. Don't do it. As soon as you have a intptr_t or void* typed context object, you can pass anything you wish to the callback, and quite efficiently at that. Yes, you can pass capturing lambdas, member methods, etc.
E.g.:
class AudioLibrary {
typedef void (*Callback)(void*);
void setOnActiveCallback(Callback cb, void * context);
};
Then:
static void functionCallback(void * context) {
auto f = reinterpret_cast<std::function<void()>*>(context);
f();
}
struct User {
AudoLibrary * m_audio;
std::function<void()> f_onActive{std::bind(&User::onActive, this)};
void onActive();
User(AudioLibrary * audio) : m_audio(audio) {
audio->setOnActiveCallback(functionCallback, &f_member);
}
};
I tried to create a subclassed control for the first time, but I feel like I did something wrong. The control is a Button, which I placed in the designer. This is its class:
class TTTField : public CButton
{
public:
BEGIN_MSG_MAP_EX(TTTField)
MSG_WM_INITDIALOG(OnInitDialog);
END_MSG_MAP()
TTTField operator=(const CWindow& btn);
private:
const BOOL OnInitDialog(const CWindow wndFocus, const LPARAM lInitParam);
};
Nothing fancy so far.
However, I can't really achieve to receive windows messages in this control. This is bad, considering the main reason for trying to subclass a control was the fact that this should be a reusable class with reusable, custom Paint behaviour. I want to overwrite certain message handlers, while keeping those I didn't explicitely ask for to the usual CButton routine.
As you can see, I implemented a message map, but the messages are just not coming in.
This is how I tried to setup the instance of this class:
TTTField fld;
is a member variable of my main dialog class. In this class I added the following DDX_MAP:
BEGIN_DDX_MAP(TTTMainDialog)
DDX_CONTROL_HANDLE(IDC_BTN, fld)
END_DDX_MAP()
with IDC_BTN being the id of the button on the designer.
In the assignment operator overload for TTTField I have the following:
TTTField TTTField::operator=(const CWindow& btn)
{
Attach(btn);
return *this;
}
I feel like this operator overload might be the source of my problems, but I just can't manage to find a website which is properly explaining the whole topic without using code which seems outdated for like 20 years.
What am I doing wrong here? I am really lost right now.
The button class should be defined as follows:
class TTTField : public CWindowImpl<TTTField, CButton>
{
protected:
BEGIN_MSG_MAP_EX(TTTField)
MSG_WM_LBUTTONDOWN(OnLButtonDown)
END_MSG_MAP()
protected:
LRESULT OnLButtonDown(UINT, CPoint)
{
//Edit: this override is meant for testing the subclass only
//it's insufficient for handling button clicks
MessageBox(L"Testing override...");
return 0;
}
};
Override dialog box's OnInitDialog, call SubclassWindow to subclass the button:
class TTTMainDialog: public CDialogImpl<CMainDialog>
{
public:
enum { IDD = IDD_MYDIALOG };
BEGIN_MSG_MAP(TTTMainDialog)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
END_MSG_MAP()
TTTField fld;
LRESULT OnInitDialog(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
fld.SubclassWindow(GetDlgItem(IDC_BTN));
return 0;
}
};
Edit, for initialization
class TTTField : public CWindowImpl<TTTField , CButton>
{
public:
void Create(CWindow *wnd, int id)
{
SubclassWindow(wnd->GetDlgItem(id));
//add initialization here
}
...
}
Then to create the button:
//fld.SubclassWindow(GetDlgItem(IDC_BTN));
fld.Create(this, IDC_BTN); //<== use this instead
Perhaps the best example, or at least one of, of subclassing a button is right in the sources of WTL, at the top of atlctrlx.h:
template <class T, class TBase = CButton, class TWinTraits = ATL::CControlWinTraits>
class ATL_NO_VTABLE CBitmapButtonImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >
{
public:
DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
...
You will also file external resources on this class: Using WTL's CBitmapButton.
That's not to mention WTL's comment on doing the controls:
// These are wrapper classes for Windows standard and common controls.
// To implement a window based on a control, use following:
// Example: Implementing a window based on a list box
//
// class CMyListBox : CWindowImpl<CMyListBox, CListBox>
// {
// public:
// BEGIN_MSG_MAP(CMyListBox)
// // put your message handler entries here
// END_MSG_MAP()
// };
More examples of simple and sophisticated custom WTL controls can be found at viksoe.dk.
A confusing thing about WTL control extension is that basic classes like CButton, CComboBox are thin wrappers over standard controls. They mostly translate methods into messages to be sent. You can often easily cast instances of such classes to HWND and back.
Standard controls themselves offer a level of customization through support of notification messages.
When you subclass a control, you are adding functionality on your side which somehow needs to interoperate with stock implementation, and control classes are no longer thin wrappers. Hence, you inherit from CWindowImpl and not CButton directly. Next challenge is to specifically subclass: you need to have original window created and after that, having a HWND handle, you modify it to route the messages through your message map. This is where you need SubclassWindow method. That is, you have the control created, you look it up its handle, e.g. with GetDlgItem and then you subclass the window using your class instance SubclassWindow call. Or, alternatively you can create the control using your new class Create method in which case CreateWindow and association with your message map will be done for you.
Some, more complicated, implementations of custom controls will also want you to reflect notification messages from parent window to the controls, so that they could handle them within the same custom control class. This will typically require that you add a line REFLECT_NOTIFICATIONS in your dialog class message map (see this related question on this).
I hope this falls within the realm of this forum:
I want to use the windows shell(?) to allow users to select a number of files before allowing my programme to do a few things to them. For this I found the MSDN sample "CommonFileDialogModes" - http://msdn.microsoft.com/en-us/library/windows/desktop/dd940350%28v=vs.85%29.aspx
In the sample under this class:
class CFileOpenBasketPickerCallback : public IFileDialogEvents, public IFileDialogControlEvents
they have this function:
// IFileDialogEvents
IFACEMETHODIMP OnFileOk(IFileDialog *pfd)
{
// if this button is in the "Add" mode then do this, otherwise return S_OK
IFileOpenDialog *pfod;
HRESULT hr = pfd->QueryInterface(IID_PPV_ARGS(&pfod));
if (SUCCEEDED(hr))
{
IShellItemArray *psia;
hr = pfod->GetSelectedItems(&psia);
if (SUCCEEDED(hr))
{
ReportSelectedItems(pfd, psia);
psia->Release();
}
pfod->Release();
}
return S_FALSE; // S_FALSE keeps the dialog up; return S_OK to allow it to dismiss.
}
which calls:
void ReportSelectedItems(IUnknown *punkSite, IShellItemArray *psia)
{
DWORD cItems;
HRESULT hr = psia->GetCount(&cItems);
for (DWORD i = 0; SUCCEEDED(hr) && (i < cItems); i++)
{
IShellItem *psi;
hr = psia->GetItemAt(i, &psi);
if (SUCCEEDED(hr))
{
PWSTR pszName;
hr = GetIDListName(psi, &pszName);
// .. I've cut some of this out for the example
CoTaskMemFree(pszName);
}
psi->Release();
}
}
}
Now I know pszName contains the names of the files selected. So I can add some extra code in to write this to disk. That works fine. But I dont want to write it to disk. I want to pass it back to the original functions that called this. The arguments for ReportSelectedItems can be altered, but IFACEMETHODIMP OnFileOk(IFileDialog *pfd) cannot as it is inherited. Adding a vector& file_names to the argument will stop it compiling.
So how should I deal with this? I could use a global variable for file_names, but everything I am learning about programming is telling me not to. It would be a quick fix, but I worry that would encourage me to be lazy in the future. I find it difficult to read the windows code and I don't really want to delve too much into the details of it. I can't even find what is calling the OnFileOk function, even though I know it is from one of the two base classes.
Do I really need to work at understanding all the library code just to get this one function doing what I'd like? Is there an faster way of going about this?
So to summarize, how would I get information from this inherited function without using a global variable or writing to disk? As I mentined before, I don't have much of a grasp of the code I am working with. And for future reference, how should I deal with this type of situation? I use c++ and would like to avoid c# and c as much as possible.
Thanks as always.
It seems a fairly big omission for Microsoft to have left out any sort of user data associated with the IFileDialog callbacks, but that does seem to be the case.
I'm assuming that simply calling GetSelectedItems() once the dialog returns is something you don't want to do for some reason - because that would obviously be the simplest solution.
From a quick look at the docs one way you may be able to pass data back from the event callback is using the owner window that you pass to IFileDialog::Show() (which is actually IModalWindow::Show()).
In the event handler, you get given the IFileDialog* pointer. From this, you can QI the address of the IOleWindow interface which will give you the dialog's window:
IFACEMETHODIMP OnFileOk(IFileDialog *pfd)
{
CComPtr<IOleWindow> pWindow;
if (SUCCEEDED(pfd->QueryInterface(IID_IOleWindow, reinterpret_cast<void**>(&pWindow))))
{
HWND hwndDlg;
if (SUCCEEDED(pWindow->GetWindow(&hwndDlg)))
{
HWND hwndOwner;
if (hwndOwner = GetWindow(hwndDlg, GW_OWNER))
{
// hwndOwner is the owner window of the dialog
}
}
}
// more code
}
Now assuming that hwndOwner is your own window, you can associate any data you like with it using SetProp()/GetProp() - so you could use this as a mechanism to pass data back from within the callback.
A simple solution was to add member data inside the inherited class and link it from the constructor:
class CFileOpenBasketPickerCallback : public IFileDialogEvents, public IFileDialogControlEvents
{
public:
CFileOpenBasketPickerCallback(vector<wstring>& files) : files_(files)
{
}
// functions
private:
vector<wstring>& files_;
};
When constructing the object
vector<std::wstring> files
CFileOpenBasketPickerCallback foacb(files);
And in IFACEMETHODIMP OnFileOk(IFileDialog *pfd)
ReportSelectedItems(pfd, psia, files_);
ReportSelectedItems is not a member so you can alter the arguments.
How can I "hide" parts of a class so that whoever is using the libary does not have to include headers for all the types used in my class. Ie take the MainWindow class below, ho can I have it so when compiled in a static/dynamic libary, whoever is useing the libary does NOT have to include windows.h, ie HWND, CRITICAL_SECTION, LRESULT, etc do not have to be defined.
I know I could split it into two classes, an abstract class with just the public interface, and an implementation class which is hidden that contains the members that require windows.h.
The problem here is that the visible class can no longer be created itsself, and an additional create function (eg CreateMainWindow) is required. That is fine in this case since it is most likly that just a single instance created on the heap is wanted but for other classes this is not.
class MainWindow
{
HWND hwnd;
int width, height;
std::string caption;
bool started,exited;
bool closeRequest;
unsigned loopThread;
CRITICAL_SECTION inputLock;
Input *input;
public:
static void init_type();
Py::Object getattr(const char *name);
MainWindow(int width, int height, std::string caption);
~MainWindow();
bool CloseRequest(const Py::Tuple &args);
bool CloseRequestReset(const Py::Tuple &args);
HWND GetHwnd();
int GetWidth();
int GetHeight();
Input* GetInput();
protected:
unsigned static __stdcall loopThreadWrap(void *arg);
unsigned LoopThreadMain();
LRESULT WndProc(UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT static CALLBACK WndProcWrapper(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
};
You can hide parts of a class using the so-called "cheshire cat", "letter/envelope", or "pimpl" technique (which are, all, different names for the same technique):
class MainWindow
{
private:
//opaque data
class ImplementationDetails;
ImplementationDetails* m_data;
public:
... declare your public methods here ...
}
The best way is probably the abstract class mentioned in your 2nd paragraph (however I failed to understand your last sentence, in which you (tried/failed to) explain what your counter-argument to that is).
As you mentioned in your question, using an abstract interface is your best option. Your DLL should have factory methods for creating/destroying instances of your concrete class. I didn't quite get your point about the downside of this.
One way or the other, you have two options:
let the library user's compiler figure out the memory size needed for your data - then the compiler can place it on stack
or allocate the data on the heap for the library user so that the user's compiler does not need to know how big the data are.
Whether you expose (2) via pimpl or MyAbstractObject *o = createMyObject() is not much different.
A third option (a hack so terrible, it's funny) creates a large byte array in the object you expose to the user, and you initialize your real objects in that array using "in-place" new. Please don't do this. I'll go and wash my brains with soap.
This book may give you some ideas:
http://www.amazon.com/Large-Scale-Software-Addison-Wesley-Professional-Computing/dp/0201633620
Large-Scale C++ Software Design
by John Lakos
As has been said before, you want to use a pimpl. I've done it and it works really well. It's totally transparent to the user of your library.