The manual says that Synchronize is a member of TThread.
However it shows that you can call Synchronize directly. Other sources tell the same.
//Synchronize() performs actions contained in a routine as if they were executed from the main VCL thread
void __fastcall TCriticalThread::Execute()
{
...
Synchronize(UpdateCaption);
...
}
But if I do this, my compiler tells me "E2268 Call to undefined function 'Synchronize'". Of course I included the library:
#include <System.Classes.hpp>
On the other hand, TThread::Synchronize is found by the compiler, but it does not accept MainThreadID as parameter:
TThread::Synchronize(MainThreadID, MainForm->UpdateCaption );
PS: I am new to C++ Builder.
Synchronize() is a method of the RTL's TThread class. In all versions of C++Builder, TThread has a non-static version of Synchronize(), which is the version the code you showed is trying to call. That requires TCriticalThread to be derived for TThread, eg:
class TCriticalThread : public TThread
{
...
protected:
virtual void __fastcall Execute();
...
};
void __fastcall TCriticalThread::Execute()
{
...
Synchronize(UpdateCaption);
...
}
If that is not the case in your situation, TThread also has a static version of Synchronize() that can be used with threads that are not derived from TThread, eg:
void __fastcall TCriticalThread::Execute()
{
...
TThread::Synchronize(NULL, UpdateCaption);
...
}
Related
I have implemented singleton of Meyers and four function to work with it. For example:
//A.h
class A
{
private:
Device d;
public:
A(){//...}
~A(){d.release();}
}
My class singleton Meyers
//Controller.h
class Controlle
{
private:
//some members
A m_member;
Controller();
Controller(const Controller&);
Controller& operator=(const Controller&);
public:
static Controller& GetInstance()
{
static Controller instance;
return instance;
}
}
And interface for working the class of Controller
extern "C" API Result InitDevice(const ParamsDevice* param);
extern "C" API Result InitAlgorithm(const ParamAlgorithm* param);
extern "C" API Result Operation_1();
extern "C" API Result Operation_2();
I build the library and get the Controller.dll and Controller.lib files. Library is shared lib.
Then I create a program where Controller.dll is used (implicit). Runtime library exception is thrown after program termination. I compiled the library in debug to check where the exception is thrown from.
I am getting the exception from comip.h file from method Release() class
template<typename _IIID> class _com_ptr_t
{
public:
// Declare interface type so that the type may be available outside
// the scope of this template.
//
typedef _IIID ThisIIID;
typedef typename _IIID::Interface Interface;
........
// Provides error-checking Release()ing of this interface.
//
void Release()
{
if (m_pInterface == NULL) {
_com_issue_error(E_POINTER);
}
else {
m_pInterface->Release();
m_pInterface = NULL;
}
}
}
I think that when the program terminates, the resources of static objects that are used in the library are incorrectly released. If I replace the singelton Meyers with a classic singelton and create methods for explicitly freeing up the memory of a static pointer, then everything works well. Could you help me explain this effect?
I think there is an answer to my question, but it is not complete for me and I cannot understand
https://stackoverflow.com/a/50644725/13970084
P.S. Sorry for my English. English isn't my native language.
I am writing a VCL componenet, TGIcon, to mimic the Icons in windows desktop, it has been working fine until I decided to add MouseEnter and MouseLeave events to the component. I followed guides from: Embarcadero Community
and here is my code (header):
class PACKAGE TGIcon : public TGraphicControl
{
private:
AnsiString FCaption;
TPngImage *FIcon, *FDIcon;
TFont *FFont;
TNotifyEvent FOnMouseEnter;
TNotifyEvent FOnMouseLeave;
void __fastcall CMMouseEnter(TMessage &Message);
void __fastcall CMMouseLeave(TMessage &Message);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(CM_MOUSEENTER, TMessage, CMMouseEnter)
MESSAGE_HANDLER(CM_MOUSELEAVE, TMessage, CMMouseLeave)
END_MESSAGE_MAP(TGIcon)
protected:
virtual void __fastcall Paint();
void __fastcall SetCaption(AnsiString value);
void __fastcall SetIcon(TPngImage *value);
void __fastcall SetFont(TFont *value);
public:
__fastcall TGIcon(TComponent* Owner);
__fastcall ~TGIcon();
void __fastcall MakeGray(void);
__published:
__property AnsiString Caption = {read=FCaption, write=SetCaption, nodefault};
__property TPngImage *Icon = {read=FIcon, write=SetIcon};
__property TFont *Font = {read=FFont, write=SetFont};
__property Parent;
__property Enabled;
__property OnClick;
__property TNotifyEvent OnMouseEnter = {read=FOnMouseEnter, write=FOnMouseEnter};
__property TNotifyEvent OnMouseLeave = {read=FOnMouseLeave, write=FOnMouseLeave};
};
Whenever I try to place the component on a Form, the IDE (C++ Builder Starter) would crash to desktop. I have traced the source of problem to be the "BEGIN_MESSAGE_MAP...END_MESSAGE_MAP" part. If I comment out that part, the component works fine.
I used to have the same component working in C++Builder XE5 (Professional) but since that's owned by a company I no longer work with, I don't have the binary of the component, so I have to re-write it here. As far as I can remember, what I did is exactly the same as the one I wrote in XE5, that one works but this one would crash the IDE, no error message, no Access Violation, just plain CTD.
Can someone please help, is there anything I need to do to make this work in C++ Builder 10.1 (Berlin) Starter Edition? Is this a bug of C++Builder or is this what cannot be done in Starter Edition, that it only can be done in the 'paid' editions?? Or is this method already obsolete? If so please show me how the "modernized" C++ Builder do it.
Thanks in advance.
Your MESSAGE_MAP is terminated incorrectly. In the END_MESSAGE_MAP macro, you must specify the base class that your component derives from (TGraphicControl).
A MESSAGE_MAP is just a fancy way to override the virtual Dispatch() method, where:
BEGIN_MESSAGE_MAP declares and opens the overridden method, and opens a switch statement
MESSAGE_HANDLER (use VCL_MESSAGE_HANDLER instead if your project uses ATL) declares case statements for the switch
END_MESSAGE_MAP calls the Dispatch() method of the specified class for unhandled messages, closes the switch, and closes the overridden method.
Here are the declarations from sysmac.h:
#define BEGIN_MESSAGE_MAP virtual void __fastcall Dispatch(void *Message) \
{ \
switch (((PMessage)Message)->Msg) \
{
#define VCL_MESSAGE_HANDLER(msg,type,meth) \
case msg: \
meth(*((type *)Message)); \
break;
// NOTE: ATL defines a MESSAGE_HANDLER macro which conflicts with VCL's macro. The
// VCL macro has been renamed to VCL_MESSAGE_HANDLER. If you are not using ATL,
// MESSAGE_HANDLER is defined as in previous versions of BCB.
//
#if !defined(USING_ATL) && !defined(USING_ATLVCL) && !defined(INC_ATL_HEADERS)
#define MESSAGE_HANDLER VCL_MESSAGE_HANDLER
#endif // ATL_COMPAT
#define END_MESSAGE_MAP(base) default: \
base::Dispatch(Message); \
break; \
} \
}
So, this code:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(CM_MOUSEENTER, TMessage, CMMouseEnter)
MESSAGE_HANDLER(CM_MOUSELEAVE, TMessage, CMMouseLeave)
END_MESSAGE_MAP(TGIcon) // <-- error!
Gets translated by the preprocessor to this code, which is what the compiler sees:
virtual void __fastcall Dispatch(void *Message)
{
switch (((PMessage)Message)->Msg)
{
case CM_MOUSEENTER:
CMMouseEnter(*((TMessage *)Message));
break;
case CM_MOUSELEAVE:
CMMouseLeave(*((TMessage *)Message));
break;
default:
TGIcon::Dispatch(Message); // <-- recursive loop!
break;
}
}
As you can see, since you are specifying your own component class (TGIcon) instead of the base class (TGraphicControl) in END_MESSAGE_MAP, you are creating an endless recursion loop when the component receives an unhandled message. TGIcon::Dispatch() is calling TGIcon::Dispatch() again. It needs to call TGraphicControl::Dispatch() instead (so do your CMMouseEnter() and CMMouseLeave() methods):
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(CM_MOUSEENTER, TMessage, CMMouseEnter)
MESSAGE_HANDLER(CM_MOUSELEAVE, TMessage, CMMouseLeave)
END_MESSAGE_MAP(TGraphicControl) // <-- fixed!
In my quest to create a cross-platform GUI Framework, I have hit the following snag:
Suppose I have a central "Window" class, in the project's general, platform-independent include folder:
//include/window.hpp
class Window
{
//Public interface
}
I then have several platform-dependent implementation classes, like so:
//src/{platform}/window.hpp
class WinWindow {...}; //Windows
class OSXWindow {...}; //OSX
class X11Window {...}; //Unix
Finally, there is the original Window class' .cpp file, where I want to "bind" the implementation class to the general class. Purely conceptually, this is what I want to be able to do:
//src/window.cpp
//Suppose we're on Windows
#include "include/window.hpp"
#include "src/win/window.hpp"
class Window : private WinWindow; //Redefine Window's inheritance
I know this is by no means valid C++, and that's the point. I have thought of two possible ways to solve this problem, and I have problems with both.
pImpl-style implementation
Make Window hold a void pointer to an implementing class, and assign that to a different window class for each platform. However, I would have to up-cast the pointer every time I want to perform a platform dependent-operation, not to mention include the platform dependent file everywhere.
Preprocessor directives
class Window :
#ifdef WIN32
private WinWindow
#else ifdef X11
private X11Window //etc.
This, however, sounds more like a hack than an actual solution to the problem.
What to do? Should I change my design completely? Do any of my possible solutions hold a little bit of water?
Using typedef to hide the preprocessor
You could simply typedef the appropriate window type instead:
#ifdef WINDOWS
typedef WinWindow WindowType;
#elif defined // etc
Then your window class could be:
class Window : private WindowType {
};
This isn't a very robust solution, though. It is better to think in a more Object Oriented way, but OO programming in C++ comes at a runtime cost, unless you use the
Curiously repeating template pattern
You could use the curiously repeating template pattern:
template<class WindowType>
class WindowBase {
public:
void doSomething() {
static_cast<WindowType *>(this)->doSomethingElse();
}
};
Then you could do
class WinWindow : public WindowBase<WinWindow> {
public:
void doSomethingElse() {
// code
}
};
And to use it (assuming C++ 14 support):
auto createWindow() {
#ifdef WINDOWS
return WinWindow{};
#elif UNIX
return X11Window{};
#endif
}
With C++ 11 only:
auto createWindow()
->
#ifdef WINDOWS
WinWindow
#elif defined UNIX
X11Window
#endif
{
#ifdef WINDOWS
return WinWindow{};
#elif defined UNIX
return X11Window{};
#endif
}
I recommend using auto when you use it, or using it in combination with a typedef:
auto window = createWindow();
window.doSomething();
Object Oriented Style
You could make your Window class be an abstract class:
class Window {
protected:
void doSomething();
public:
virtual void doSomethingElse() = 0;
};
Then define your platform-dependent classes as subclasses of Window. Then all you'd have to do is have the preprocessor directives in one place:
std::unique_ptr<Window> createWindow() {
#ifdef WINDOWS
return new WinWindow;
#elif defined OSX
return new OSXWindow;
// etc
}
Unfortunately, this incurs a runtime cost through calls to the virtual function. The CRTP version resolves calls to the "virtual function" at compile time instead of at runtime.
Additionally, this requires the Window to be declared on the heap whereas CRTP doesn't; this might be a problem depending on the use case, but in general, it doesn't matter that much.
Ultimately, you do have to use the #ifdef somewhere, so you can determine the platform (or you could use a library that determines the platform, but it probably uses #ifdef too), the question is just where to hide it.
You can use the CRTP pattern to implement static polymorphism:
class WindowBase {
virtual void doSomething() = 0;
};
template<class WindowType>
class Window : public WindowBase {
// Static cast when accessing the actual implementation:
void doSomething() {
static_cast<WindowType*>(this)->doSomethingElse();
}
};
class X11WindowImpl : public Window<X11WindowImpl> {
void doSomethingElse() {
// blah ...
}
};
class Win32WindowImpl : public Window<Win32WindowImpl> {
void doSomethingElse() {
// blah ...
}
};
Since your code will be compiled to satisfy a particular target, this should be the leanest option.
It's okey. You could also write one class and define it's content using #ifdef etc., but your solution isn't a hack. Just a proper way to write multiplatform code if you have no other choice.
I have been googling high and low and can't find a solution that will remove the warning, even when I use the using directive.
class TShowException_Form : public TForm {
__published: // IDE-managed Components
TButton *Send_Button;
TButton *Cancel_Button;
TLabel *Message_Label;
private: // User declarations
using TCustomForm::ShowModal;
//using TForm::ShowModal;
public: // User declarations
__fastcall TShowException_Form(TComponent* Owner);
int __fastcall ShowModal(System::Sysutils::Exception *E);
};
I want to hide the original virtual int __fastcall ShowModal(void) and expose a new one taking an Exception parameter.
But it still complaints on "hides virtual function":
[bcc32 Warning] TShowExceptionForm.h(32): '_fastcall TShowException_Form::ShowModal(Exception *)' hides virtual function '_fastcall TCustomForm::ShowModal()'
I have also tried using TForm::ShowModal; but with the same result.
Any ideas of how to solve this warning?
EDIT
I found out that it works perfectly well if I override the show() method instead:
class TShowException_Form : public TForm {
__published: // IDE-managed Components
TButton *Send_Button;
TButton *Cancel_Button;
TLabel *Message_Label;
private: // User declarations
using TForm::ShowModal;
using TForm::Show;
public: // User declarations
__fastcall TShowException_Form(TComponent* Owner);
int __fastcall Show(System::Sysutils::Exception *E);
};
So why isn't it working with ShowModal()?
bcc32 is, in many respects, not very compliant with the C++ standard. Whenever I find myself asking, "Why does this technique that I think should work in C++ not work in bcc32?", I usually assume it's yet another compiler bug.
The fact that Show works while ShowModal doesn't is interesting. Looking at Vcl.Forms.hpp shows the difference: Show is defined with HIDESBASE (a macro that expands to __declspec(hidesbase)).
Adding HIDESBASE to your ShowModal should work as well. You may also have to declare a virtual destructor, if you don't already have one, due to bcc32 compiler weirdness.
virtual __Fastcall ~TShowException_Form() {}
You must declare overloaded version as virtual too:
virtual int __fastcall ShowModal(System::SysUtils::Exception * E);
Does not know if C++Builder supports C++11, but if it does, try also to delete overload which you want to hide:
virtual int __fastcall ShowModal() = delete;
instead of placing it into private section.
You get the warning because what you are trying to do happens very often by mistake and is a serious and very hard to find bug if it is done by mistake. Maybe you should use a different name.
I am currently working on a project that uses a DLL and an application that uses the DLL. The DLL is exported as an abstract base class header and a concrete implementation derived from the abstract base, as usual:
---- TaskInterface.h ----
class Task {
public:
virtual int func1(void) = 0;
virtual int func2(void) = 0;
};
extern "C" __declspec(dllexport) Task * APIENTRY newTask();
--- Task.h ---
class TaskImpl : public Task
{
public:
virtual int func1(void);
virtual int func2(void):
};
Task * APIENTRY newTask()
{
return static_cast<Task*>( new TaskImpl );
}
--- Task.cpp ---
int TaskImpl::func1(void)
{
// ...
}
int TaskImpl::func2(void)
{
// ...
}
This works so far as intended, the application includes "AbstractTask.h" and then calls the respective function defined by class TaskImpl:
--- TheApplication.cpp ---
Task aTask = newTask();
aTask->func1();
aTask->func2();
// ...
However, now the Application discovers that what the default implementation in class TaskImpl does is not enough and therfore defines within its own scope a new derived class, like so:
--- AppImpl.h ---
#include "TaskInterface.h"
class AppImpl : public Task
{
int func1(void) = { /* new stuff */ }
int func2(void) = { /* new stuff */ }
};
and then defines in TheApplication.cpp:
--- TheApplication.cpp ---
#include "AppImpl.h"
ApplImp * aNewTask = static_cast<Task*>(newTask());
aNewTask->func1();
aNewTask->func2();
In what context do you think func1() and func2() are called? Correct: It's still the concrete implementation inside the DLL class TaskImpl and not the derivates defined by class AppImpl.
And basically this is my problem: I want to use a default implementation from inside a DLL, but I want to be able to expand it on the Application side, so unless I have explicitly overriden a function in ApplImp.h, I fall back to the one defined in TaskImpl inside the DLL.
Is this possible? If so, what am I doing wrong? If not, how could I accomplish something equivalent?
I already toyed with exporting both "TaskInterface.h" and "Task.h" and then have ApplImp.h include the concrete class in the DLL, but the compile doesn't like that for obvious reasons => can't export newTask() twice.
Any help is appreciated!
As you need to allocate and deallocate via the DLL anyway, I'd suggest providing a wrapper class alongside the DLL. This wrapper class then could be designed to be inherited from.
class Task {
public:
virtual int func1(void) = 0;
virtual int func2(void) = 0;
};
// v~~~~v probably dllimport in the header you ship
extern "C" __declspec(dllexport) Task * APIENTRY newTask();
class TaskWrapper {
public:
TaskWrapper() : m_ptr( newTask() ) {}
virtual ~TaskWrapper() { deleteTask(m_ptr); }
virtual int func1(void) { m_ptr->func1(); }
virtual int func2(void) { m_ptr->func2(); }
protected: // implementation omitted for brevity
TaskWrapper(TaskWrapper const&);
TaskWrapper(TaskWrapper&&);
TaskWrapper& operator= (TaskWrapper const&);
TaskWrapper& operator= (TaskWrapper&&);
private:
Task* m_ptr; // preferably a unique_ptr
};
You could also let TaskWrapper derive from Task.
If I understand the question correctly, you want ApplImp to derive from TaskImp, and call into TaskImpl member implementations as needed, using standard C++ syntax..
You can't do that directly because the application and DLL are linked separately and have no compile-time knowledge of each other. The application doesn't know about TaskImpl at compile time, thus the compiler cannot derive from it and cannot create a Vtable that may be a combination of funcitons from application and DLL.
You chould compose the objects, i.e. create an instance of TaskImp inside ApplImp and delegate all functions to the TaskImp instance inside of ApplImp. That's inconvenient in many cases.
A more convenient way is to export the implementation of TaskImpl from the DLL: declare the whole class as __dllexport. Unfortunately, that's the least portable way to do it and in a large project, it may lead to a huge dll export section with 10000 C++-name-mangled entries. But you might be able to use TaskImpl as a base class in other DLLs or the application.
Btw, this won't compile because ApplImp is derived from Task, and Task* cannot be cast implicitly to ApplImpl.
ApplImp * aNewTask = static_cast(newTask());