C++ Builder 12中使用RTTI创建TValue<TNotifyEvent>时类型转换异常问题
解决RTTI赋值TNotifyEvent事件属性的类型转换异常问题
问题原因
TNotifyEvent是闭包函数指针void (__closure *)(TObject*)的typedef别名。用TValue::From<TNotifyEvent>生成TValue时,RTTI关联的是底层函数指针的类型信息,而非TNotifyEvent这个typedef的类型信息。但事件属性的RTTI类型是TNotifyEvent,导致SetValue时因类型不匹配触发EInvalidCast异常。
直接赋值btn->OnClick = &closeBtnClick;能正常工作,是因为编译期编译器会自动处理typedef别名的类型匹配;而RTTI是运行期机制,要求类型信息严格一致。
解决方案
通过TValue::Make方法手动指定TNotifyEvent的类型信息,让TValue关联正确的RTTI类型:
方法1:直接生成正确的TValue
修改调用代码:
// 先创建TNotifyEvent类型的 handler TNotifyEvent handler = &closeBtnClick; // 用Make方法指定TNotifyEvent的TypeInfo生成TValue auto value = TValue::Make(&handler, __typeinfo(TNotifyEvent)); setProperty(btn, "OnClick", value);
方法2:基于TMethod的正确实现
如果需要通过RTTI获取方法地址,修正后的代码如下:
auto* context = getContext(); auto* method = context->GetType(__classid(TStandardPanel))->GetMethod("closeBtnClick"); TMethod tm; tm.Code = method->CodeAddress; tm.Data = this; // 将TMethod转换为TNotifyEvent,再用Make指定类型信息 TNotifyEvent handler = reinterpret_cast<TNotifyEvent>(tm); auto value = TValue::Make(&handler, __typeinfo(TNotifyEvent)); setProperty(btn, "OnClick", value);
验证说明
修改后,value.TypeInfo->Name会显示为TNotifyEvent,与事件属性的类型信息完全匹配,调用SetValue时就不会触发类型转换异常了。
内容的提问来源于stack exchange,提问作者Ингибитор Палладиум
相关产品推荐
相关产品推荐

