MVP Logo

Материализуя идеи

Не поднимешься в горы — не узнаешь высоты неба; не спустишься в бездну — не узнаешь толщи земли.

В Дельфи есть удобный сервис создания объектов\компонентов из известного метакласса этого объекта\компонента.

В C++ Builder такого сервиса язык С++ не предоставляет (насколько я знаю), даже с учетом его нестандартных расширений Embarcadero. Реализовать недостающий функционал можно используя симбиоз из pas и cpp. Кроме того, надо понимать, что этот подход работает только для чистых Delphi объектов. С++ класс, порожденный от базового Delphi класса, это уже гибрид, который с помощью такого метода создавать небезопасно.

  • Создаем модуль паскаля с необходимыми нам сервисами (у меня он называется EsCoreGuiSysUtilities.pas):

unit EsCoreGuiSysUtilities;

/// Special utility stuff that may be implemented only in Delphi Pascal language
///
interface

uses
  System.Classes,
  FMX.Types,
  FMX.TextLayout;

function objectCreate( meta: TClass ) : TObject; overload;
function objectCreate( meta: TComponentClass; owner: TComponent ) : TComponent; overload;
function textLayoutCreate( meta: TTextLayoutClass; const canvas: TCanvas ) : TTextLayout;

implementation

function objectCreate( meta: TClass ) : TObject;
begin
  result := meta.Create();
end;

function objectCreate( meta: TComponentClass; owner: TComponent ) : TComponent;
begin
  result := meta.Create( owner );
end;

function textLayoutCreate( meta: TTextLayoutClass; const canvas: TCanvas ) : TTextLayout;
begin
  result := meta.Create( canvas );
end;

begin 
end.

  • Включаем исходник на паскале в наш С++ проект. NB! Исходники паскаля компилируются прежде исходников на c\cpp, поэтому к началу работы компилятора С++ у нас уже будет автоматически создан заголовочный файл, соответствующий паскалевскому модулю:
// CodeGear C++Builder
// Copyright (c) 1995, 2013 by Embarcadero Technologies, Inc.
// All rights reserved

// (DO NOT EDIT: machine generated header) 'EsCoreGuiSysUtilities.pas' rev: 25.00 (Windows)

#ifndef EscoreguisysutilitiesHPP
#define EscoreguisysutilitiesHPP

#pragma delphiheader begin
#pragma option push
#pragma option -w-      // All warnings off
#pragma option -Vx      // Zero-length empty class member 
#pragma pack(push,8)
#include <System.hpp>	// Pascal unit
#include <SysInit.hpp>	// Pascal unit
#include <System.Classes.hpp>	// Pascal unit
#include <FMX.Types.hpp>	// Pascal unit
#include <FMX.TextLayout.hpp>	// Pascal unit

//-- user supplied -----------------------------------------------------------

namespace Escoreguisysutilities
{
//-- type declarations -------------------------------------------------------
//-- var, const, procedure ---------------------------------------------------
extern DELPHI_PACKAGE System::TObject* __fastcall objectCreate(System::TClass meta)/* overload */;
extern DELPHI_PACKAGE System::Classes::TComponent* __fastcall objectCreate(System::Classes::TComponentClass meta, System::Classes::TComponent* owner)/* overload */;
extern DELPHI_PACKAGE Fmx::Textlayout::TTextLayout* __fastcall textLayoutCreate(Fmx::Textlayout::TTextLayoutClass meta, Fmx::Types::TCanvas* const canvas);
}	/* namespace Escoreguisysutilities */
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_ESCOREGUISYSUTILITIES)
using namespace Escoreguisysutilities;
#endif
#pragma pack(pop)
#pragma option pop

#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif	// EscoreguisysutilitiesHPP
  • Теперь мы можем просто использовать созданный на паскале функционал в С++. Т.к. я это делал для использования в своей библиотеке, в namespace EsUtilities, то соответствующие вызовы библиотеки были перенаправлены в вызовы паскалевского модуля.

в EsUtilities.h:

/// Utilities namespace
///
namespace EsUtilities
{
/// Create Delphi object instance from its metaclass
EKOSF_COREGUI_FUNC TObject* NEW(TMetaClass* mc);

/// Create Delphi component instance from its metaclass
EKOSF_COREGUI_FUNC TComponent* NEW(TComponentClass mc, TComponent* Owner);

/// Create FMX TTextLayout object from its metaclass
EKOSF_COREGUI_FUNC TTextLayout* NEW(TTextLayoutClass tlc, TCanvas* const canvas = 0);

в EsUtilities.cpp:

#include "EsCoreGuiUtilities.h"
#include "EsCoreGuiSysUtilities.hpp"

TObject* EsUtilities::NEW(TMetaClass* mc)
{
	ES_ASSERT(mc);

	return Escoreguisysutilities::objectCreate(mc);
}
//---------------------------------------------------------------------------

TComponent* EsUtilities::NEW(TComponentClass cc, TComponent* Owner)
{
	ES_ASSERT(cc);

	return Escoreguisysutilities::objectCreate(cc, Owner);
}
//---------------------------------------------------------------------------

TTextLayout* EsUtilities::NEW(TTextLayoutClass tlc, TCanvas* const canvas /*= 0*/)
{
	ES_ASSERT(tlc);

	return Escoreguisysutilities::textLayoutCreate(tlc, canvas);
}
//---------------------------------------------------------------------------

Яндекс.Метрика

Сейчас на сайте 144 гостя и нет пользователей

07.08.2020  ©2020 - ExactSoft - All rights reserved