我正在使用C++ Builder 10.2。
在Android中,我想将各种消息(包括主线程)发送到主GUI线程。在Windows中,我可以发布一条消息,并将LPARAM或WPARAM分配给结构或类的某些实例的地址。
我正在尝试使用System.Messaging.TMessageManager
做同样的事情,类似于此处的示例:System.Messaging (C++)。但是我只能发送“简单”类型,例如UnicodeString
或int
。我什至没有想出如何发送一个指针,假设它甚至有可能。
我想发送一个这样的结构/类实例:
class TSendResult
{
public:
String Message;
unsigned int Value;
int Errno;
__fastcall TSendResult(void);
__fastcall ~TSendResult();
};
如果可以做到,该怎么写?我设法得到一个版本进行编译,但是出现了链接器错误:error: undefined reference to 'vtable for System::Messaging::TMessage__1<TSendResult>'
表单构造函数:
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
TMessageManager* MessageManager = TMessageManager::DefaultManager;
TMetaClass* MessageClass = __classid(TMessage__1<TSendResult>);
TMessageListenerMethod ShowReceivedMessagePointer = &(this->MMReceiveAndCallBack);
MessageManager->SubscribeToMessage(MessageClass, ShowReceivedMessagePointer);
}
按钮点击处理程序:void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
...
TSendResult *SPtr = new TSendResult();
SPtr->Message = "All good";
SPtr->Value = 10;
SPtr->Errno = 0;
TMessageManager* MessageManager = TMessageManager::DefaultManager;
TMessage__1<TSendResult>* Message = new TMessage__1<TSendResult>(*SPtr); // <-- this doesn't look right...
MessageManager->SendMessage(Sender, Message, false);
}
捕获消息的功能:void __fastcall TForm1::MMReceiveAndCallBack(System::TObject* const Sender,
System::Messaging::TMessageBase* const M)
{
TMessage__1<TSendResult>* Message = dynamic_cast<TMessage__1<TSendResult>*>(M);
if (Message) {
ShowMessage(Message->Value.Message);
}
}
最佳答案
TMessage__1<T>
是Delphi通用 TMessage<T>
类的C++类实现。不幸的是,在C++中使用Delphi泛型类时有一个已记录的限制,这就是为什么出现链接器错误的原因:
How to Handle Delphi Generics in C++
Delphi generics are exposed to C++ as templates. However, it is important to realize that the instantiations occur on the Delphi side, not in C++. Therefore, you can only use these template for types that were explicitly instantiated in Delphi code.
...
If C++ code attempts to use a Delphi generic for types that were not instantiated in Delphi, you'll get errors at link time.
这就是
TMessage__1<UnicodeString>
有效而TMessage__1<TSendResult>
不起作用的原因,因为Delphi RTL中存在TMessage<UnicodeString>
的实例化。您正在看的谁写了C++ example,可能都不知道此限制,而只是按原样翻译了Delphi example。话虽如此,您有两种选择:
.pas
单元,将TSendResult
实现为Delphi record
,并为其定义TMessage<TSendResult>
的实例化。然后,您可以在C++代码中使用该单元(编译.hpp
文件时,C++ Builder会为您生成一个C++ .pas
文件),例如:unit MyMessageTypes;
interface
uses
System.Messaging;
type
TSendResult = record
Message: String;
Value: UInt32;
Errno: Integer;
end;
TSendResultMsg = TMessage<TSendResult>;
implementation
initialization
TSendResultMsg.Create.Free;
finalization
end.
#include "MyMessageTypes.hpp"
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
TMessageManager::DefaultManager->SubscribeToMessage(__classid(TSendResultMsg), &MMReceiveAndCallBack);
}
void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
...
TSendResult Res;
Res.Message = _D("All good");
Res.Value = 10;
Res.Errno = 0;
TSendResultMsg *Message = new TSendResultMsg(Res);
TMessageManager::DefaultManager->SendMessage(this, Message, true);
}
void __fastcall TForm1::MMReceiveAndCallBack(System::TObject* const Sender,
System::Messaging::TMessageBase* const M)
{
const TSendResultMsg* Message = static_cast<const TSendResultMsg*>(M);
ShowMessage(Message->Value.Message);
}
TMessage__1
,而是可以直接从 TSendResult
派生TMessageBase
,例如:class TSendResultMsg : public TMessageBase
{
public:
String Message;
unsigned int Value;
int Errno;
};
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
TMessageManager::DefaultManager->SubscribeToMessage(__classid(TSendResultMsg), &MMReceiveAndCallBack);
}
void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
...
TSendResultMsg *Message = new TSendResultMsg;
Message->Message = _D("All good");
Message->Value = 10;
Message->Errno = 0;
TMessageManager::DefaultManager->SendMessage(this, Message, true);
}
void __fastcall TForm1::MMReceiveAndCallBack(System::TObject* const Sender,
System::Messaging::TMessageBase* const M)
{
const TSendResultMsg* Message = static_cast<const TSendResultMsg*>(M);
ShowMessage(Message->Message);
}
关于android - FMX系统消息传递以发送指针(?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64312162/