Edit: Now that I have a better idea of what is going on, I think I can better phrase this question so it is more useful.
I am trying to replicate the following delphi code in C++
TThread.Queue(nil,
procedure
begin
LogMessage("test");
end
);
The purpose of the code is to call a method which updates a TMemo
on a form in a thread safe manner. Here is the C++ version of the method I am trying to call with Thread.Queue
void __fastcall TClientForm::LogMessage( String message )
{
MemoLog->Lines->Add( message );
}
Because I am using a BCC32 compiler without CLANG enhancements, using a Lambda is not an option. Instead according to this documentation I need to create a class which inherits from TThreadProcedure
which overrides the Invoke()
method to do the work I need done. Then I can pass an instance of that class into TThread::Queue
.
I created the following class which inherits TThreadProcuedure
and contains an invoke method.
class TMyThreadProcedure : TThreadProcedure
{
void __fastcall Invoke( String message );
};
However, since TThreadProcedure
is an abstract class, I cannot simply create an instance of it to pass into TThread::Queue
. What is the proper way to inherit from TThreadProcedure
and define a function to be called when I pass an instance of my class into TThread::Queue
?
As stated in the documentation:
How to Handle Delphi Anonymous Methods in C++
You have two choices:
derive a class 1 that implements the appropriate interface (in this case, Classes::TThreadProcedure
), overriding the Invoke()
method to do your desired work. You can then pass an instance of that class to TThread::Queue()
. For example:
class TLogMessageRef : public TCppInterfacedObject<Classes::TThreadProcedure>
{
private:
TClientForm *form;
public:
TLogMessageRef(TClientForm* _form) : form(_form) {}
INTFOBJECT_IMPL_IUNKNOWN(TInterfacedObject);
void __fastcall Invoke()
{
form->LogMessage("test");
}
};
TThread::Queue(NULL,
Classes::_di_TThreadProcedure(
new TLogMessageRef(this)
)
);
(1 the use of TCppInterfacedObject
and INTFOBJECT_IMPL_IUNKNOWN
is covered elsewhere in the documentation: Inheritance and Interfaces)
The documentation also provides a reusable TMethodRef
class to help with the implementation, if you need to use anonymous methods/procedures in multiple places of your code:
Using a Functor (Function Object)
For example:
struct LogMsg
{
TClientForm* form;
LogMsg(TClientForm *_form) : form(_form) {}
void operator()()
{
form->LogMessage("test");
}
};
typedef TMethodRef<Classes::TThreadProcedure, LogMsg, void> MyMethRef;
TThread::Queue(NULL,
Classes::_di_TThreadProcedure(
new MyMethRef(
LogMsg(this)
)
)
);
in the Clang-based C++11 compilers only, you can use a C++ lambda anywhere an anonymous procedure/method is expected:
TThread::Queue(NULL,
[this]() -> void { LogMessage("test"); }
);