How to implement the Delphi protected member access trick in C++ builder? - delphi

I need access to TControlItem.InternalSetLocation which is protected. I Delphi you would do
type
THackControlItem = class(TControlItem);
How do you do this in C++ Builder?

As in Delphi, you need to inherit the class but also override and make public the protected function. However, I wouldn't recommend to use it in production code.
class THackControlItem : public TControlItem
{
public:
void __fastcall InternalSetLocation(int AColumn, int ARow, bool APushed, bool MoveExisting)
{
TControlItem::InternalSetLocation(AColumn, ARow, APushed, MoveExisting);
}
};
In the program
TControlItem* ci = ...;
static_cast<THackControlItem*>(ci)->InternalSetLocation(...);

This is a nice trick I think Remy Lebeau showed me but can not find the QA anymore...
//---------------------------------------------------------------------------
#ifndef _TDirectMemoryStream
#define _TDirectMemoryStream
class TDirectMemoryStream:TMemoryStream // just for accessing protected SetPointer
{
public:
void SetMemory(BYTE *ptr,DWORD siz) { SetPointer(ptr,siz); Position=0; };
};
#endif
//---------------------------------------------------------------------------
You simply create new class that is descendant of the class you want to access. Now just add get/set functions for the protected members ...
Now usage:
TMemoryStream *mem=new TMemoryStream(); // original class instance you want to access
// overtype to our new class and access/use you get/set ...
((TDirectMemoryStream*)(mem))->SetMemory(hdr->lpData,hdr->dwBytesUsed);
delete mem; // release if not needed anymore
I am using it btw to feed a memory stream with custom memory data hdr coming from vfw camera so I can properly decode it using TJPEGImage class instead of writing the data into file and loading it back each frame ...
Here another example:
class A
{
protected:
int x;
public:
int getx(){ return x; }
};
class hack_A:A
{
public:
void setx(int _x){ x=_x; }
};
void test()
{
A a;
hack_A *ha=(hack_A*)&a;
ha->setx(10);
a.getx(); // print the x somwhere
}
However this will not work for private members ... In such case its doable too but requires access to A source code:
class A
{
protected:
int x;
private:
int y;
public:
int getx(){ return x; }
int gety(){ return y; }
friend class hack_A; // but this one requires access to A soourcecode
};
class hack_A:A
{
public:
void setx(int _x){ x=_x; }
void sety(int _y){ y=_y; }
};
void test()
{
A a;
hack_A *ha=(hack_A*)&a;
ha->setx(10);
ha->sety(20);
a.getx(); // print the x somwhere
a.gety(); // print the x somwhere
}

Related

An object reference is required for the nonstatic field, method, or property into dotnet core [duplicate]

Consider:
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//int[] val = { 0, 0};
int val;
if (textBox1.Text == "")
{
MessageBox.Show("Input any no");
}
else
{
val = Convert.ToInt32(textBox1.Text);
Thread ot1 = new Thread(new ParameterizedThreadStart(SumData));
ot1.Start(val);
}
}
private static void ReadData(object state)
{
System.Windows.Forms.Application.Run();
}
void setTextboxText(int result)
{
if (this.InvokeRequired)
{
this.Invoke(new IntDelegate(SetTextboxTextSafe), new object[] { result });
}
else
{
SetTextboxTextSafe(result);
}
}
void SetTextboxTextSafe(int result)
{
label1.Text = result.ToString();
}
private static void SumData(object state)
{
int result;
//int[] icount = (int[])state;
int icount = (int)state;
for (int i = icount; i > 0; i--)
{
result += i;
System.Threading.Thread.Sleep(1000);
}
setTextboxText(result);
}
delegate void IntDelegate(int result);
private void button2_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
Why is this error occurring?
An object reference is required for the nonstatic field, method, or property 'WindowsApplication1.Form1.setTextboxText(int)
It looks like you are calling a non static member (a property or method, specifically setTextboxText) from a static method (specifically SumData). You will need to either:
Make the called member static also:
static void setTextboxText(int result)
{
// Write static logic for setTextboxText.
// This may require a static singleton instance of Form1.
}
Create an instance of Form1 within the calling method:
private static void SumData(object state)
{
int result = 0;
//int[] icount = (int[])state;
int icount = (int)state;
for (int i = icount; i > 0; i--)
{
result += i;
System.Threading.Thread.Sleep(1000);
}
Form1 frm1 = new Form1();
frm1.setTextboxText(result);
}
Passing in an instance of Form1 would be an option also.
Make the calling method a non-static instance method (of Form1):
private void SumData(object state)
{
int result = 0;
//int[] icount = (int[])state;
int icount = (int)state;
for (int i = icount; i > 0; i--)
{
result += i;
System.Threading.Thread.Sleep(1000);
}
setTextboxText(result);
}
More info about this error can be found on MSDN.
For this case, where you want to get a Control of a Form and are receiving this error, then I have a little bypass for you.
Go to your Program.cs and change
Application.Run(new Form1());
to
public static Form1 form1 = new Form1(); // Place this var out of the constructor
Application.Run(form1);
Now you can access a control with
Program.form1.<Your control>
Also: Don't forget to set your Control-Access-Level to Public.
And yes I know, this answer does not fit to the question caller, but it fits to googlers who have this specific issue with controls.
You start a thread which runs the static method SumData. However, SumData calls SetTextboxText which isn't static. Thus you need an instance of your form to call SetTextboxText.
Your method must be static
static void setTextboxText(int result)
{
if (this.InvokeRequired)
{
this.Invoke(new IntDelegate(SetTextboxTextSafe), new object[] { result });
}
else
{
SetTextboxTextSafe(result);
}
}
Credit to #COOLGAMETUBE for tipping me off to what ended up working for me. His idea was good but I had a problem when Application.SetCompatibleTextRenderingDefault was called after the form was already created. So with a little change, this is working for me:
static class Program
{
public static Form1 form1; // = new Form1(); // Place this var out of the constructor
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(form1 = new Form1());
}
}
I actually got this error because I was checking InnerHtml for some content that was generated dynamically - i.e. a control that is runat=server.
To solve this I had to remove the "static" keyword on my method, and it ran fine.
From my looking you give a null value to a textbox and return in a ToString() as it is a static method. You can replace it with Convert.ToString() that can enable null value.
Make the function static. This must solve your problem.
The essence, and solution, to your problem is this:
using System;
namespace myNameSpace
{
class Program
{
private void method()
{
Console.WriteLine("Hello World!");
}
static void Main(string[] args)
{
method();//<-- Compile Time error because an instantiation of the Program class doesnt exist
Program p = new Program();
p.method();//Now it works. (You could also make method() static to get it to work)
}
}
}

store a lambda that captures this

Using C++ 17, I'm looking for a way to store a lambda that captures the this pointer, without using std::function<>. The reason to not using std::function<> is that I need the guaranty that no dynamic memory allocations are used. The purpose of this, is to be able to define some asynchronous program flow. Example:
class foo {
public:
void start() {
timer(1ms, [this](){
set_pin(1,2);
timer(1ms, [this](){
set_pin(2,1);
}
}
}
private:
template < class Timeout, class Callback >
void timer( Timeout to, Callback&& cb ) {
cb_ = cb;
// setup timer and call cb_ one timeout reached
...
}
??? cb_;
};
Edit: Maybe it's not really clear: std::function<void()> would do the job, but I need / like to have the guaranty, that no dynamic allocations happens as the project is in the embedded field. In practice std::function<void()> seems to not require dynamic memory allocation, if the lambda just captures this. I guess this is due to some small object optimizations, but I would like to not rely on that.
You can write your own function_lite to store the lambda, then you can use static_assert to check the size and alignment requirements are satisfied:
#include <cstddef>
#include <new>
#include <type_traits>
class function_lite {
static constexpr unsigned buffer_size = 16;
using trampoline_type = void (function_lite::*)() const;
trampoline_type trampoline;
trampoline_type cleanup;
alignas(std::max_align_t) char buffer[buffer_size];
template <typename T>
void trampoline_func() const {
auto const obj =
std::launder(static_cast<const T*>(static_cast<const void*>(buffer)));
(*obj)();
}
template <typename T>
void cleanup_func() const {
auto const obj =
std::launder(static_cast<const T*>(static_cast<const void*>(buffer)));
obj->~T();
}
public:
template <typename T>
function_lite(T t)
: trampoline(&function_lite::trampoline_func<T>),
cleanup(&function_lite::cleanup_func<T>) {
static_assert(sizeof(T) <= buffer_size);
static_assert(alignof(T) <= alignof(std::max_align_t));
new (static_cast<void*>(buffer)) T(t);
}
~function_lite() { (this->*cleanup)(); }
function_lite(function_lite const&) = delete;
function_lite& operator=(function_lite const&) = delete;
void operator()() const { (this->*trampoline)(); }
};
int main() {
int x = 0;
function_lite f([x] {});
}
Note: this is not copyable; to add copy or move semantics you will need to add new members like trampoline and cleanup which can properly copy the stored object.
There is no drop in replacement in the language or the standard library.
Every lambda is a unique type in the typesystem. Technically you may have a lambda as a member, but then its type is fixed. You may not assign other lambdas to it.
If you really want to have an owning function wrapper like std::function, you need to write your own. Actually you want a std::function with a big enough small-buffer-optimization buffer.
Another approach would be to omit the this capture and pass it to the function when doing the call. So you have a captureless lambda, which is convertible to a function pointer which you can easily store. I would take this route and adapter complexer ways if really nessessary.
it would look like this (i trimmed down the code a bit):
class foo
{
public:
void start()
{
timer(1, [](foo* instance)
{
instance->set_pin(1,2);
});
}
private:
template < class Timeout, class Callback >
void timer( Timeout to, Callback&& cb )
{
cb_ = cb;
cb_(this); // call the callback like this
}
void set_pin(int, int)
{
std::cout << "pin set\n";
}
void(*cb_)(foo*);
};

How to add a 2-times derived class of TCollectionItem to TOwnedCollection?

I want to implement a collection or list using TOwnedCollection / TCollectionItem. I need a persistent list (to load and create from a FileStream) of classes with polymorphism.
Here is (part of) my code so far, but I didn't succeed to create the derived class TGenerator instead of its parent TPowerComponent and add it to the Collection.
//-------------------------------------------------------------------------------------
class TPCCollection : public TOwnedCollection
{
typedef TOwnedCollection inherited;
private:
TPowerComponent* __fastcall GetPowerComponent(int Index);
void __fastcall SetPowerComponent(int Index, TPowerComponent *Value);
public:
__fastcall TPCCollection(TPersistent *Owner);
HIDESBASE TPowerComponent* __fastcall Add(void);
HIDESBASE TPowerComponent* __fastcall Insert(int Index);
__property TPowerComponent* PCCollection[int Index] = {read=GetPowerComponent, write=SetPowerComponent};
};
//-------------------------------------------------------------------------------------
class TPowerComponent : public TCollectionItem
{
typedef TCollectionItem inherited;
public :
int X, Y, Rotation;
PowSymbType HisType;
__fastcall TPowerComponent(TCollection *Collection, PowSymbType AType );
void __fastcall Assign(TPersistent *Source);
virtual void __fastcall Paint(TCanvas * Canvas);
};
//-------------------------------------------------------------------------------------
class TGenerator : public TPowerComponent
{
typedef TPowerComponent inherited;
public :
double PG, Qgmin, Qgmax, Vsch;
__fastcall TGenerator(TCollection *Collection, PowSymbType AType );
void __fastcall Assign(TPersistent *Source);
virtual void __fastcall Paint(TCanvas * Canvas);
};
//-------------------------------------------------------------------------------------
// implementation
//-------------------------------------------------------------------------------------
// TPCCOllection
//-------------------------------------------------------------------------------------
__fastcall TPCCollection::TPCCollection(TPersistent *Owner)
: TOwnedCollection(Owner, __classid(TPowerComponent))
{
}
//-------------------------------------------------------------------------------------
TPowerComponent* __fastcall TPCCollection::Add()
{
return static_cast<TPowerComponent>(inherited::Add());
}
//-------------------------------------------------------------------------------------
TPowerComponent* __fastcall TPCCollection::Insert(int Index)
{
return static_cast<TPowerComponent>(inherited::Insert(Index));
}
//-------------------------------------------------------------------------------------
TPowerComponent* __fastcall TPCCollection::GetPowerComponent(int Index)
{
return static_cast<TPowerComponent>(inherited::GetItem(Index));
}
//-------------------------------------------------------------------------------------
void __fastcall TPCCollection::SetPowerComponent(int Index, TPowerComponent *Value)
{
inherited::SetItem(Index, Value);
}
//-------------------------------------------------------------------------------------
// TPowerComponent
//-------------------------------------------------------------------------------------
__fastcall TPowerComponent::TPowerComponent(TCollection *Collection, PowSymbType AType )
: TCollectionItem(Collection)
{
HisType=AType;
Rotation=0;
}
//-------------------------------------------------------------------------------------
void __fastcall TPowerComponent::Assign(TPersistent *Source)
{
TPowerComponent *Src = dynamic_cast<TPowerComponent>(Source);
if( Src )
{
// copy members from Src...
}
else inherited::Assign(Source);
}
//-------------------------------------------------------------------------------------
// se dessine
void __fastcall TPowerComponent::Paint(TCanvas * Canvas)
{
...
}
//-------------------------------------------------------------------------------------
// TGenerator
//-------------------------------------------------------------------------------------
__fastcall TGenerator::TGenerator(TCollection *Collection, PowSymbType AType )
:TPowerComponent( Collection, AType )
{
PG=0; Qgmin=0; Qgmax=0; Vsch=1.0; Con=-1;
}
//-------------------------------------------------------------------------------------
void __fastcall TGenerator::Assign(TPersistent *Source)
{
TGenerator *Src = dynamic_cast<TGenerator>(Source);
if( Src )
{
// copy members from Src...
}
else inherited::Assign(Source);
}
//-------------------------------------------------------------------------------------
// Usage
TPCCollection * NetWork = new TPCCollection(this);
// Usage to Access all the collection
for( int i=0; i< NetWork->Count; i++)
{
((TPowerComponent*)(NetWork->Items[i]))->Paint(Canvas);
}
To add a TGenerator and not a TPowerComponent, I use:
TGenerator * Gen=new TGenerator( NetWork, Generator);
The creation of the TCollectionItem child automatically add itself to the TCollection
The problem here is that we can't separate the process of item creation from adding it to the collection.
When I need another list that can have some of the items of the first collection list, for example, SelectedComponents can have one or some of the Items of the NetWork Collection, without recreating them.
This can be done with
std::list<TPowerComponent*> SelectedComponents;
but I can't write/read them using FileStream / persistent list. I need to put them in a TCollection but without recreating them.
How?
The RTL's native DFM streaming for TCollection objects only partially supports polymorphic TCollectionItem classes.
You can add polymorphic TCollectionItem objects to a TCollection in code (at runtime, as well as at design-time with the aid of a custom editor), as long as they all derive from a common base class that is passed to the TCollection constructor. And such a collection can even be saved as-is to a DFM.
However, when loading back a DFM, native streaming will force all collection items read from the DFM to use whatever TCollectionItem class type you pass to the TCollection constructor. So, polymorphic classes can't be loaded natively.
The only way to override that behavior is to disable native streaming for the collection (make your TCollection property be non-published, or at least mark it as stored=false), and then stream the collection items manually.
Have your main component (or whatever TPersistent class owns the collection) override the virtual DefineProperties() method to call TFiler.DefineProperty() to register custom reading/writing methods for streaming the collection items. To support polymorphic classes, you will have to write each item's ClassName to the DFM before writing its property values, then read the name back so you know which class to instantiate before then reading property values.

dependency injection in Arduino

I've started working with Arduino and I want to do a time share system so I do not use the delay command.
I have a problem when I try to register objects that inherit from another.
Here I have a test code that should show in the terminal: "Wow wow Miuau miuau ..."
I have doubts when I try to create an Interface and how do I declare the register () function so that Cat and Dog objects can be entered in the Animal type Array.
The following code is only to show the problem:
class Animal {
public:
void message() {
}
};
class Dog : public Animal {
public:
void message() {
Serial.println("Guau guau");
}
};
class Cat : public Animal {
public:
void message() {
Serial.println("Miau miau ");
}
};
class Multiplex {
private:
int index = 0;
Animal objects[5];
public:
void register(Animal object) {
objects[index] = object;
index++;
}
void go() {
for(int i = 0;i<index;i++) {
objects[i].message();
}
}
};
Dog dog;
Cat cat;
Multiplex multiplex;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
multiplex.register(dog);
multiplex.register(cat);
}
void loop() {
// put your main code here, to run repeatedly:
multiplex.go();
delay(1000);
}
Any help is welcome ...
Thanks and sorry for my english.
In this case you have to use polymorphism (virtual methods). But it still won't work with so many copies of "registered" object into the Animal base class (it shows nothing because Animal::message() is called). You have to use pointers (or references - but it's not so easy in this case)
class Animal { // pure virtual class (abstract class)
public:
virtual void message() = 0; // The '= 0;' makes whole class "pure virtual"
};
class Dog : public Animal {
public:
virtual void message() {
Serial.println("Guau guau");
}
};
class Cat : public Animal {
public:
virtual void message() {
Serial.println("Miau miau ");
}
};
class Multiplex {
private:
int index = 0;
Animal * objects[5];
public:
void reg(Animal * object) { // pass pointer to the object
objects[index] = object; // object must be valid for whole time
index++;
}
void go() {
for(int i = 0;i<index;i++) {
objects[i]->message();
}
}
};
Dog dog;
Cat cat;
Multiplex multiplex;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
multiplex.reg(&dog);
multiplex.reg(&cat);
}
void loop() {
// put your main code here, to run repeatedly:
multiplex.go();
delay(1000);
}
If you don't like dynamic polymorphism, you have to use something like object type, switch and typecasting to its correct type.

boost::asio and boost::bind errors

This questions is a bit annoying, I can't get the following code to compile. You will have to compile the code below.
I am having some trouble with boost asio, I am trying to abstract the logic of accepting connections into a uniform abstraction so that I can initiate connection for windows named-pipes and Unix domain sockets uniformly with regular TCP/IP.
There are 3 classes shown in the code below, the first 2 are the implementations of acceping TCP connections, and the third class below is a generic class that is implemented in terms of the first 2. I am having troubles with boost::bind calls. The trouble probably lies with my understanding of the semantics.
If I make TcpDestinationAcceptor::handle_accept a regular member function (--i.e., not a template member function) which results in me not passing the AcceptHandler parameter. The code compiles fine. Note: I do not remove the template function status from TcpDestinationAcceptor::StartAccepting.
Note: I have already started on a different design, still I would like to pursue this design if possible.
Self contained code:
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/asio/placeholders.hpp>
class TcpDestinationConnection
{
public:
typedef boost::asio::ip::tcp::socket t_io_object;
TcpDestinationConnection(boost::asio::io_service & io_s)
: m_io_object(io_s) {} ;
t_io_object & io_object() { return m_io_object; }
private:
t_io_object m_io_object;
};
class TcpDestinationAcceptor
{
public:
typedef boost::asio::ip::tcp::acceptor t_acceptor;
typedef boost::shared_ptr<TcpDestinationConnection> t_connection_ptr;
TcpDestinationAcceptor( boost::asio::io_service & io_s)
: m_io_service(io_s),
m_acceptor(io_s)
{
m_acceptor.open(boost::asio::ip::tcp::v4());
}
TcpDestinationAcceptor( boost::asio::io_service & io_s ,
const boost::asio::ip::tcp::endpoint & endpoint)
: m_io_service(io_s),
m_acceptor(io_s, endpoint)
{
m_acceptor.open(boost::asio::ip::tcp::v4());
}
t_acceptor & acceptor() { return m_acceptor; }
template<typename AcceptHandler>
void StartAccepting(AcceptHandler h)
{
t_connection_ptr new_session(new TcpDestinationConnection(m_io_service));
m_acceptor.async_accept( new_session->io_object(),
boost::bind( &TcpDestinationAcceptor::handle_accept<AcceptHandler>, this,
boost::asio::placeholders::error, new_session, h));
}
template<typename AcceptHandler>
void handle_accept(const boost::system::error_code & err, t_connection_ptr cur, AcceptHandler h) {
}
private:
boost::asio::io_service & m_io_service;
boost::asio::ip::tcp::acceptor m_acceptor;
};
template<typename t_acceptor>
class ConnectionOracle
{
public:
ConnectionOracle()
: m_io_service(),
m_acceptor(m_io_service) {}
typename t_acceptor::t_acceptor & native_acceptor() { return m_acceptor.acceptor(); }
boost::asio::io_service & io_service() { return m_io_service; }
void StartConnection( typename t_acceptor::t_connection_ptr connection,
boost::system::error_code & error)
{
}
void Begin()
{
m_acceptor.StartAccepting( boost::bind( &ConnectionOracle::StartConnection,this,
_1,
boost::asio::placeholders::error));
m_io_service.run();
}
private:
boost::asio::io_service m_io_service;
t_acceptor m_acceptor;
};
int main()
{
ConnectionOracle<TcpDestinationAcceptor> ConOracle;
ConOracle.native_acceptor().
bind(boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),50000));
ConOracle.Begin();
return 0;
}

Resources