|
To be specific about what @k5054 wrote, use std::unique_ptr [^] whenever possible. There's also shared_ptr and weak_ptr for a pointer with multiple owners (shared) or users (weak).
|
|
|
|
|
Hey Greg, there`s more than one issue in the function I posted. Like how do you go about managing a pointer that has been passed to the function.
I`ve seen this code in a codeproject article:
void NukeA(A* p)
{
p->DoThis();
p->DoThat();
delete p;
p = nullptr;
}
My thought is that this is wrong because the original pointer (the pointer being passed) remains at the gates of the function unaffected by the changes inside NukeA();
void NukeSafelyA(A** p)
{
(*p)->DoThis();
(*p)->DoThat();
delete *p;
*p = nullptr;
}
My question is how do you go about assigning a pointer to the pointer being passed or assign the pointer being passed to a new pointer that is stated/declared in the body of the function;
void NukeSafelyA(A** p)
{
(*p)->DoThis();
(*p)->DoThat();
A * Temp1;
A * Temp2;
(*p) = Temp1;
Temp2 = (*p);
delete *p;
*p = nullptr;
}
modified 24-Mar-22 12:13pm.
|
|
|
|
|
Setting a pointer to nullptr after invoking delete on it is definitely recommended. Or in C, setting it to NULL after invoking free . To do it, pass the pointer by reference:
void NukeSafelyA(A*& p)
{
p->DoThis();
p->DoThat();
delete p;
p = nullptr;
}
|
|
|
|
|
Us old-school C programmers tend to forget about the existence of references. Well done, Greg. That's far cleaner than the pointer-to-pointer version the OP presented, but does exactly the same thing.
To the OP:
On the whole though, except as a learning exercise, and some really rare, odd cases, the STL should be the way to go. It's likely to be safer, perhaps faster, and certainly far better tested than your own implementation. The STL should be part of your basic tool kit for C++ programming.
Keep Calm and Carry On
|
|
|
|
|
Thanks guys. As you lean stuff, you begin to understand things that you previously heard about but never really understood. I`m taking the std pointers as a new horizon, at this point I feel that they are remote from where I am. I`ll be using the default c++ approach.
|
|
|
|
|
I am using a property sheet for my app to adjust the options and GUI elements. When the file opens, the app has two tabs created via Addview and all of that is working. OnInitialUpdate sets the styles because it uses the registry settings when it starts. What I'm trying to do is have the styles adjust on an OnApply when the user selects the style they want. I have the OutputPane working correctly which is shown in the code below. What I can't get to work is to have the document tabs change on a Recalc/Redraw .
BOOL CSettingsUserTabs::OnApply()
{
BOOL bResult = CMFCPropertyPage::OnApply();
if (bResult)
{
AfxGetApp()->WriteProfileInt(_T("Settings"), _T("UserTabStyle"), m_style_tabs);
((CMainFrame*)AfxGetMainWnd())->m_wndOutput.m_wndTabs.ModifyTabStyle((CMFCTabCtrl::Style)m_style_tabs);
((CMainFrame*)AfxGetMainWnd())->m_wndOutput.m_wndTabs.RecalcLayout();
CMFCTabCtrl& MDI_STYLES = ((CMainFrame*)AfxGetMainWnd())->GetMDITabs();
MDI_STYLES.ModifyTabStyle((CMFCTabCtrl::Style)m_style_tabs);
MDI_STYLES.RecalcLayout();
CMDIFrameWndEx* pMainFrame = DYNAMIC_DOWNCAST(CMDIFrameWndEx, GetTopLevelFrame());
pMainFrame->SetFocus();
pMainFrame->RecalcLayout();
}
return bResult;
}
Any ideas what I can do solve this problem? I've scoured the net for examples on how to solve this issue and yet to get it to work. There is a TabControl solution in the Microsoft master repository to show how it works, but since I'm using a propertysheet to control it, the example does work but the example doesn't use the AddView so I can't use it as a good example.
Here is the code that loads the RUNTIME_CLASSES where the tabs are created:
void CMovieView::OnInitialUpdate()
{
AddView(RUNTIME_CLASS(CTabView1), AfxStringID(IDS_TAB1));
AddView(RUNTIME_CLASS(CTabView2), AfxStringID(IDS_TAB2));
GetTabControl().EnableTabSwap(TRUE);
GetTabControl().SetLocation(CMFCBaseTabCtrl::Location::LOCATION_TOP);
GetTabControl().EnableAutoColor(TRUE);
int UserTabStyle = AfxGetApp()->GetProfileInt(_T("Settings"), _T("UserTabStyle"), 0);
if (UserTabStyle != FALSE && UserTabStyle <= 8) {
int EnumUserTabStyle = UserTabStyle - 1;
GetTabControl().ModifyTabStyle(static_cast<CMFCTabCtrl::Style>(EnumUserTabStyle));
}
else {
GetTabControl().ModifyTabStyle(CMFCTabCtrl::STYLE_FLAT);
}
CTabView::OnInitialUpdate();
}
This works on creation, I can't get it to work when the OnApply() is used because you can't recall OnInitialUpdate for something already created. I can't seem to get GetTabControl() to work after on create as a separate function....so I'm unclear on how to solve this problem. Does anyone have any ideas on how I can modify my code to get it working?
Thanks,
Chris
|
|
|
|
|
I hope it is ok to put LAST action first -
0 attempt to bypass what has been done /said so far .
This is a result of all discussions so far .
I have modified the call by adding "std:bind" . That bypasses the limits of passing five parameters to the QtConcurrent.
The suspected issue of passing the pointers now generate several errors.
I am trying to analyze one of them , posted here.
Could use some help doing that.
// hci_inquiry as extern function with arguments
//hci_inquiry(int dev_id, int len, int num_rsp,
//const uint8_t *lap, inquiry_info **ii, long flags);
QFuture<int> future_hci = QtConcurrent::run(
std::bind(
hci_inquiry,
dev_id,
len,
num_rsp,
lap,
ii,
flags));
This error reports the result of wrong "type" , however I do not see which of the passed parameters is syntactically wrong - hence wrong " type ".
This is the first error in compiler output - there are 10 of them all saying wrong "type " is passed in .
/usr/include/c++/11/functional:464: error: no type named ‘type’ in ‘struct std::result_of<int (*&(int&,="" int&,="" const="" unsigned="" char*&,="" inquiry_info*&,="" int&))(int,="" int,="" char*,="" inquiry_info**,="" long="" int)="">’
/usr/include/c++/11/functional:498:9: required from ‘void QtConcurrent::StoredFunctorCall0<t, functionpointer="">::runFunctor() [with T = int; FunctionPointer = std::_Bind<int (*(int,="" int,="" const="" unsigned="" char*,="" inquiry_info*,="" int))(int,="" inquiry_info**,="" long="" int)="">]’
../../../QT/15/5.15.2/gcc_64/include/QtConcurrent/qtconcurrentstoredfunctioncall.h:60:10: required from here
/usr/include/c++/11/functional:464:15: error: no type named ‘type’ in ‘struct std::result_of<int (*&(int&,="" int&,="" const="" unsigned="" char*&,="" inquiry_info*&,="" int&))(int,="" int,="" char*,="" inquiry_info**,="" long="" int)="">’
464 | using _Res_type_impl
| ^~~~~~~~~~~~~~
..and this is the last error
/usr/include/c++/11/functional:464: error: no type named ‘type’ in ‘struct std::result_of<int (*="" const="" volatile&(const="" volatile="" int&,="" unsigned="" char*="" volatile&,="" inquiry_info*="" int&))(int,="" int,="" char*,="" inquiry_info**,="" long="" int)="">’
/usr/include/c++/11/functional:540:9: required from ‘void QtConcurrent::StoredFunctorCall0<t, functionpointer="">::runFunctor() [with T = int; FunctionPointer = std::_Bind<int (*(int,="" int,="" const="" unsigned="" char*,="" inquiry_info*,="" int))(int,="" inquiry_info**,="" long="" int)="">]’
../../../QT/15/5.15.2/gcc_64/include/QtConcurrent/qtconcurrentstoredfunctioncall.h:60:10: required from here
/usr/include/c++/11/functional:464:15: error: no type named ‘type’ in ‘struct std::result_of<int (*="" const="" volatile&(const="" volatile="" int&,="" unsigned="" char*="" volatile&,="" inquiry_info*="" int&))(int,="" int,="" char*,="" inquiry_info**,="" long="" int)="">’
464 | using _Res_type_impl
| ^~~~~~~~~~~~~~
ORIGINAL POST
I hope I can describe the problem.
This is a variation on "time consuming process".
The tool (object) I am using can initialize and run another thread to process
such time consuming task.
The function running the task is "extern" and its name and parameters are passed to the object.
That works fine when such extern function is declared / defined locally.
(when the function is defined locally and the parameter passed have no defined value - compiler complains...good)
The function I like to use is part of compiled library,
hence no (local /extern) source code.
Can I do this - without the source code ?
modified 22-Mar-22 10:01am.
|
|
|
|
|
I'm net entirely clear on what you're trying to do.
Normally, a library that is expected to be used by a developer is supplied with a header file that describes the contents of the library, that is #includ ed in the source file of user created software. That's what stdio.h or iostream do for you. If at all possible, you should look for the developer tools for your library and use the supplied headier.
Alternatively - and this is only as a last resort for the well-informed and foolhardy, there's no reason you can't declare the function in your own source code. But, you really have to know what the function signature is. If you have a mismatch, then you're almost certainly going to invoke Undefined Behavior, and then all bets about the validity of anything your program produces is suspect.
So for example, we know that the signature for a cosine function in the c standard library is double cos(double x; . Now normally we would write
#include <math.h>
double val = cos(2.5);
But it's perfectly valid to write
double cos(double x);
double val = cos(2.5);
But as I state above, you need to be sure that you've got the right signature for your function. If for example we were to write
double cos(int x); double val = cos(2.5)
/ ... Then the compiler will convert the 2.5 to an integer (e.g. a 4 byte value containing the value 0x02), and then pass that to the math library cos() function. On the library side, the code is expecting a double (e.g an 8 byte value in IEEE floating point format), so it will dutifully use the top 8 bytes of the stack for the value to calculate the cosine for. As you can see, we've only put 4 bytes on the stack in our call, and so half the data its using to calculate is, in essence, random data. Clearly, in this case we can't rely on what value cos() returns to us.
This is not the same as passing an int to cos() that has been properly declared. In that case, the compiler knows that the cos() function is expecting a double as its argument, so it provides a conversion from int to double at compile time.
Keep Calm and Carry On
|
|
|
|
|
I was afraid my description will be poor..,.,
So here is a code snippet.
I am posting it for info only - I had to move stuff around to get a single shot - so it will probably not compile.
The primary task of my test QtConcurrent (cFunction) is to build a new thread and run it
QFuture<int> future_c = QtConcurrent::run(cFunction, param);
QtConcurrent::run does build a new thread and runs cFunction with passed param and returns such param. Works as expected.
Now I want to do same for hci_inquiry function.
That is where I am stuck.
1. do I have to do this ?
extern int hci_inquiry(int dev_id, int len, int num_rsp, const uint8_t *lap, inquiry_info **ii, long flags);
2. do I have to "define " hci_inguiy at all ?
I can execute hci_inquiry as "plain" function - but it takes up to 30 seconds to complete and QT does not like that - in my view it gets stuck in some "event loop " - no good.
3. if I "declare "
extern int hci_inquiry(int dev_id, int len, int num_rsp, const uint8_t *lap, inquiry_info **ii, long flags);
it sort of passes compiler but I get error saying that "run" does not exists.
This is where my statement about "ducks" came from
I do not know if I am not writing the parameters correctly or the "declaration" of the function is wrong.
4. Compiler will not compile if passed parameters have not been defined , hence have no values assigned to them. I do not get that error with hci_inquiry, but the missing "RUN" may mask that - again are the ducks all there ?
Again - this is test code - not intended to compile and run.
I am NOT asking about QT - I just do not get why the "run" won't process hci_inquiry function.
int cFunction(int param )
{
qDebug() <<" TEST QtConcurrent c Function ";
return 10*param;
};
int param = 5;
extern int cFunction(int param);
QFuture<int> future_c = QtConcurrent::run(cFunction, param);
int TESTResult = future_c.result();
qDebug() <<" END RUN TEST QtConcurrent a Function ";
QFuture<int> future_hci = QtConcurrent::run(
hci_inquiry,
dev_id,
len,
num_rsp,
lap,
ii,
flags);
aDDENDUM
NO MATCHING FUNCTION FOR CALL TO 'RUN"
IS THE actual error message
MORE ADDEEDUM
This is QT QConcurrent run example I am copying
extern void aFunctionWithArguments(int arg1, double arg2, const QString &string);
int integer = ...;
double floatingPoint = ...;
QString string = ...;
QFuture<void> future = QtConcurrent::run(aFunctionWithArguments, integer, floatingPoint, string);
My parameters are definitely wrong , I am not sure how to "code / syntax " the single and double pointers.
modified 21-Mar-22 23:02pm.
|
|
|
|
|
|
I'll take a risk here
if I post plain function call hci-inquiry which WORKS and
SAME function -
hci-inquiry
with identical parameters passed to it AND wrapped in QTCreator / QTConcurrent object
WHICH DOES NOT work
will somebody here help me to find the problem ?
I am not asking for how to RTFM - I am looking for real C/C++ code help.
|
|
|
|
|
First, the function you are trying to call is hci_inquiry not hci-inquiry . The second is an invalid identifier, and the compiler should be trying to parse this as hci - inqury . Not the same thing at all.
Second, looking at the documentation (RTFM! RTFM!), it looks like you probably want to use Qt::Concurrent::run() . Maybe start another thread and include the code that (a) works and (b) fails - plus what the failure mode is. As it is I'm blindly guessing at what you're doing and what may or may not be going wrong for you.
Third, Maybe look for a QT support forum. This forum isn't really intended to help with QT, but with C, C++ or MFC. I think I'm safe in saying that QT lies outside those bounds. It might be that there's noone here particularly well versed in QT.
Keep Calm and Carry On
|
|
|
|
|
OK, I made a typo.
Irregardless - I think it is relevant that I said one of the calls works and the other does not .
I am getting nowhere in QT forum , and I do not care to discuss it.
I have been thru "try this and try that ' with my test code.
So - let's cut thru the chase
here is my test code snippet
THIS ONE WORKS
so the syntax is OK
status = hci_inquiry(
dev_id,
len,
max_rsp,
NULL,
&ii,
flags);
THIS ONE DOES NOT WORK
QFuture<void> future_hci = QtConcurrent::run(
std::bind(
hci_inquiry,
dev_id,
len,
max_rsp,
NULL,
&ii,
flags)
);
/
What is the difference ?
and this is first of series of errors posted
<pre>/media/q5/MDI/QT_PROGRAMS/QT/15/5.15.2/gcc_64/include/QtConcurrent/qtconcurrentstoredfunctioncall.h:60: error: no match for call to ‘(std::_Bind<int (*(int, int, int, long int, inquiry_info**, int))(int, int, int, const unsigned char*, inquiry_info**, long int)>) ()’
In file included from ../../../QT/15/5.15.2/gcc_64/include/QtConcurrent/qtconcurrentrun.h:49,
from ../../../QT/15/5.15.2/gcc_64/include/QtConcurrent/QtConcurrent:16,
from /mnt/sde5/QT_PROGRAMS_FULL/MDI_BT/MDI_BT/SUB_FT857/mainwindow_sub_ft857.cpp:15:
../../../QT/15/5.15.2/gcc_64/include/QtConcurrent/qtconcurrentstoredfunctioncall.h: In instantiation of ‘void QtConcurrent::StoredFunctorCall0<T, FunctionPointer>::runFunctor() [with T = int; FunctionPointer = std::_Bind<int (*(int, int, int, long int, inquiry_info**, int))(int, int, int, const unsigned char*, inquiry_info**, long int)>]’:
../../../QT/15/5.15.2/gcc_64/include/QtConcurrent/qtconcurrentstoredfunctioncall.h:60:10: required from here
../../../QT/15/5.15.2/gcc_64/include/QtConcurrent/qtconcurrentstoredfunctioncall.h:60:57: error: no match for call to ‘(std::_Bind<int (*(int, int, int, long int, inquiry_info**, int))(int, int, int, const unsigned char*, inquiry_info**, long int)>) ()’
60 | void runFunctor() override { this->result = function(); }
| ~~~~~~~~^~
and this is more
<pre>/usr/include/c++/11/functional:464: error: no type named ‘type’ in ‘struct std::result_of<int (*&(int&, int&, int&, long int&, inquiry_info**&, int&))(int, int, int, const unsigned char*, inquiry_info**, long int)>’
/usr/include/c++/11/functional:498:9: required from ‘void QtConcurrent::StoredFunctorCall0<T, FunctionPointer>::runFunctor() [with T = int; FunctionPointer = std::_Bind<int (*(int, int, int, long int, inquiry_info**, int))(int, int, int, const unsigned char*, inquiry_info**, long int)>]’
../../../QT/15/5.15.2/gcc_64/include/QtConcurrent/qtconcurrentstoredfunctioncall.h:60:10: required from here
/usr/include/c++/11/functional:464:15: error: no type named ‘type’ in ‘struct std::result_of<int (*&(int&, int&, int&, long int&, inquiry_info**&, int&))(int, int, int, const unsigned char*, inquiry_info**, long int)>’
464 | using _Res_type_impl
| ^~~~~~~~~~~~~~
what are these errors telling me ?
I DO NOT KNOW
if I knew I could fix it , duh...
I am asking for help...
|
|
|
|
|
Looking at the documentation at Concurrent Run | Qt Concurrent 5.15.8[^], it suggests you should be able to write:
QFuture<void> future_hci = QtConcurrent::run(
hci_inquiry,
dev_id,
len,
max_rsp,
NULL,
&ii,
flags);
But as k5054 already said, this is the C/C++ forum. For Qt issues you need to find a specialist forum. My feeling would be to write a small test program using the Qt run function with different parameters to check that it does work for the different situations. Once you overcome that issue then you should be able to focus more on the HCI stuff.
|
|
|
|
|
No, I cannot "just write ..." QTconcurent will not accept more than 5 parameters, hence std:bind is used to bypass that.
I believe I need somebody who can interpret the errors.../.
|
|
|
|
|
Member 14968771 wrote: QTconcurent will not accept more than 5 parameters,
What's your source for this statement. The docs Concurrent Run | Qt Concurrent 5.15.8 do not mention any limit. Assuming that its a C++ template using a parameter pack, the only limit I would expect would be your pthread stack size, which defaults to 8M, so for all intents an purposes not an issue.
One thing I would note is that hci_inquiry returns an int so I think the template parameter to QFuture should probablby be:
QFuture<int> future = QTconcurrent::run( ... )
Keep Calm and Carry On
|
|
|
|
|
I got this second hand and did not bother to verify the parameters # limit.
I am busy rebuilding my text code and will be able to try the function without std::bind.
Well - until I can get pass the errors I really do not care if the return values is wrong.
That puts me back to the original post - how do I know which is causing the error - wrong parameters , wrong # of parameters , incorrect return ... all of these are C++_ issues , very little to do with QT.
( ...but for some who cannot read it looks as QT problem...)
Cheers
|
|
|
|
|
Here us my latest test code
it does prove that
Qt Concurrent takes max of five "arguments" and lets leave it be...
Secondly
I found the "ducks" error.
And not sure how to react to it.
QT passes "arguments" to the run function ,
then QT expect / does this ( as a example )
int integer = 5;
if the argument is of "TYPE" integer.
( I have not tried to assign any arbitrary symbol )
then QT expect the symbol "integer" to passed as (??) to the "run" function...
..and it it fails , it identifies the failure source as "TYPE"
not as parameter or argument - just "TYPE"...
Maybe that is normal , but what a pain to debug.
extern int bFunction(
int arg1,
int arg2,
int arg3,
int arg4,
int arg5,
int arg6,
int arg7,
int arg8
);
int integer = 5;
QFuture<int> future = QtConcurrent::run(
std::bind(
bFunction,
integer,
integer,
integer,
integer,
integer,
integer,
integer,
integer
)
);
|
|
|
|
|
Did some testing of my own over the weekend and I can confirm that QtConcurrent::run() does not like more than 5 parameters. Maybe the thing to do is to look into std::async, std::future as it does not seem to be limited and provides the same functionality. There's a couple of videos on them here: C++ Weekly - Ep 9 std::future Quick-Start - YouTube and here: C++ Weekly - Ep 11 std::future Part 2 - YouTube. Unless there's something in QtConcurrent that ties in better with your QT project, std::async and std::future may server you better.
As a point of interest, why QT? If you're on Ubuntu, and not using Kubuntu, I would have thought that maybe GTK+ would provide a more consistent look-&-feel. There are C++ bindings available (gtkmm), so if you're on a QT/C++ learning curve it would be about the same for you. There's no integrated IDE with gtk, but there's plenty of IDE's out there that will play nicely. Or you could go "hardcore" and learn how to write Makefiles!
Keep Calm and Carry On
|
|
|
|
|
I appreciate confirmation of the parameters # limit .
I do not see why QT limitation of one process would be a reason to switch OS, especially when
using std::bind "fixes " this limitation.
I have SUCCESSFULLY codded and run several test function using QTConcurrent,
and I am basically back where I started.
I could use some more assistance with this.
The attached code is direct from QT documentation.
What I do not understand is the necessity of highlighted code.
What is the purpose and is there a doc I could RTFM to get some
understanding why this code is necessary.
If I pass the aFunctionWithArguments function arguments at face value I then get
the "type" error ( as posted previously )
Is this something "just QT " or is that "normal" C++
and if so what is the correct terminology of doing this ?
I just call it "SYMBOLS".
My real code gets complicated because I am a passing more the 5 "arguments" and two of them are
pointer and double pointer.
I can run my test function passing struct and have no need for these "SYMBOLS".
I am NOT asking to write my code, I am asking for explanation why
QT is using these "conversions / symbols "
extern void aFunctionWithArguments(int arg1, double arg2, const QString &string);
int integer = ...;
double floatingPoint = ...;
QString string = ...;
QFuture<void> future = QtConcurrent::run(aFunctionWithArguments, integer, floatingPoint, string);
|
|
|
|
|
Member 14968771 wrote: ( ...but for some who cannot read it looks as QT problem...) Adding comments like that is unnecessary, and does not encourage people to help further.
|
|
|
|
|
Member 14968771 wrote: QTconcurent will not accept more than 5 parameters Reminds me of when I worked for a company about to publish a completely rewritten FORTRAN compiler: The release was pushed by one (significant) customer who had run into the old compiler's limit on 99 (ninety-nine) parameters to one function. The new compiler would allow 128 parameters, but it could easily be extended to 256 in future compiler versions.
I sort of accept that when going above a certain limit (isn't it 4 for the ARM ABI?), there is an increased cost. Five is probably acceptable. The day it grows beyond 99, I think you are on the wrong track 
|
|
|
|
|
It reminds me of an adage or axiom or some such that my prof stated in class back in university days that went something like "If you function has more than 5 parameters, you've forgotten one!"
Keep Calm and Carry On
|
|
|
|
|
I merely said, "the documentation suggests ...". I do not have Qt on my system so I am not able to test it.
|
|
|
|
|
As a debugging note
if just the number of parameters passed, irregardless if the are "plain arguments" or these funky symbols
do not match -
the error is "run" " cannot find the function " .
The "TYPE" error is definitely my wrong way of "symbolizing" the pointers.
Unfortunately the error does not clearly identify which "symbol" is not correct.
I'll try to find a real hci function which does not use pointers to verify this assumption.
|
|
|
|
|