Dear Konstantin and others,
our recent discussion stimulated my curiosity and I wrote a small frontend for the trigger board of our experiment in C++.
The underlying hardware details are not relevant here. I would just like to briefly report and discuss what I found out.
I have written all the frontend files (but the bus driver) in C++11:
- my_frontend.cpp
- driver/class/my_class_driver.cpp
- driver/device/my_device_driver.cpp
All went quite smoothly, but I feel that the overall structure is still very C-like (that may be a good thing or a bad thing depending on the point of view).
As far as I know, the MIDAS frontend mfe.c has still only the C version (I couldn't find any mfe.cxx). This means that all the points of contact between the MIDAS frontend code and the user
frontend code must be C compatible (no C++ features or name mangling). To accomplish this I needed to slightly modify the midas.h header file like this:
@@ -1141,7 +1141,13 @@ typedef struct eqpmnt {
+#ifdef __cplusplus
+extern "C" {
+#endif
INT device_driver(DEVICE_DRIVER *device_driver, INT cmd, ...);
+#ifdef __cplusplus
+}
+#endif
I also tested the new strcomb1 function and it seems to work OK.
I have attached a source file to show how I implemented the device driver in C++. The code is not meant to be compilable: it is just to show how I implemented it. This is the most C++-like syntax that I could come out with. Feel free to comment it and if you think that it could be improved let me know.
Best Regards
Giorgio
|
class myDevice {
private:
// Here goes what in C was the MY_DEVICE_INFO struct
MY_DEVICE_SETTINGS m_settings; /* Settings struct of the device */
void *m_bd_info; /* private info of bus driver */
HNDLE m_hkey; /* ODB key for bus driver info */
INT m_channels; /* number of channels */
public:
myDevice( HNDLE hkey, INT channels, INT(*bd) (INT cmd, ...) )
{
// Here goes what in C was my_device_init
}
INT myCommand(INT channel, ... /* other arguments */ )
{
// Implementation of my_command
}
~myDevice()
{
// Here goes what in C was my_device_exit
}
};
/*---- device driver entry point -----------------------------------*/
INT my_device(INT cmd, ...)
{
va_list argptr;
HNDLE hKey;
INT channels, channel, status;
float *pvalue;
myDevice *pMyDevice;
INT (*bd) (INT, ...);
va_start(argptr, cmd);
status = FE_SUCCESS;
switch (cmd) {
case CMD_INIT:
hKey = va_arg(argptr, HNDLE);
pMyDevice = va_arg(argptr, myDevice *);
channels = va_arg(argptr, INT);
va_arg(argptr, DWORD); // flags
bd = va_arg(argptr, INT (*) (INT, ...));
try { pMyDevice = new myDevice(hKey, channels, bd); }
catch (const std::exception& e) {
cm_msg(MERROR, __func__, " init: %s", e.what());
status = FE_ERR_DRIVER;
};
break;
case CMD_MY_COMMAND:
pMyDevice = va_arg(argptr, myDevice *);
channel = va_arg(argptr, INT);
// other arguments
try { status = pMyDevice->myCommand(channel, /* other arguments */); }
catch (const std::exception& e) {
cm_msg(MERROR, __func__, " my command: %s", e.what());
if (status == FE_SUCCESS) status = FE_ERR_DRIVER;
}
break;
case CMD_EXIT:
pMyDevice = va_arg(argptr, myDevice *);
pMyDevice->~myDevice();
break;
default:
break;
}
va_end(argptr);
return status;
}
|