How i can declare a global method in Oxygene - delphi-prism

How i can declare a global method in delphi prism using the __Global class?
And It is recommended to use global methods?
unfortunately I have not found any example.

Yes, you can if you turn on the Allow Globals option in your project options. Then you can just do the following code:
interface
method GlobalMethod: Integer; public;
implementation
It is not recommended to use this construction. A more .Net way is to use a static/class method on a class.
type
TSomeClass = public class
public
class method GlobalMethod: Integer;
end;
// Call like this
I := TSomeClass.GlobalMethod;

Related

Delphi: Threads and Generic

I am just trying to pass a generic type to the execute method of a TThread. I can't figure it out...
procedure MyThread.Execute;
begin
Obj := TDWResponseType.FromJsonString<T>(Response);
end;
Should I use a threadvar, How can I cast It ?
When you call TDWResponseType.FromJsonString<T> generic type T must be either explicitly defined or must be available as T from the outer context. There is not T available in the outer context and such code will not compile.
In your particular case, either MyThread class must be generic class or Execute method must be generic method.
Assuming that MyThread class is TThread descendant, then modifying Execute method is out of option.
You have two options:
declare MyThread<T> instead of MyThread
use specific class in TDWResponseType.FromJsonString<TSomeClass>
Thank you guys:
procedure TMyThread<T>.Execute; // with: TMyThread<T: class, constructor>=class(TThread)
begin
TJson.JsonToObject<T>(Response);
end;

Visual C++: ATL Implementation of an Interface

I guess this is a real dumb question, but I couldn't find an answer. I'm trying to implement an COM interface using ATL. According to this I should use the Implement Interface Wizard. My question is how can I find the desired interface in this wizard. Do I have to go over all the libraries? Does is specified somewhere in the documentation of the interface (IOleCommandTarget)
To implement an interface you need:
inherit your class from it
add it onto interface map
implement its methods
For example:
class CFoo :
// regular COM object base class, esp. those generated by ATL Simple Object Class Wizard
public IOleCommandTarget
{
BEGIN_COM_MAP(CFoo)
// ...
COM_INTERFACE_ENTRY(IOleCommandTarget)
END_COM_MAP()
// ...
public:
// IOleCommandTarget
STDMETHOD(Exec)(...) // IOleCommandTarget methods go here
{
// ...
}
};
To implement you need to do:
In the *h file let your CoClass inherit from interface.
2.In the *h file ,add an interface entry in the COM Map.
In the *h file ,add the prototype of interface methods.
In the *cpp file, implement the method of interface.

Simple singleton pattern - Visual C++ assertion failure

I'm recently programming a very simple logger class in Visual C++ 2010, but I have a problem. Everytime I run the program, a debug assertion failure appears.
Expression: _CrtIsValidHeapPointer(pUserData)
This is how my class looks like (basically it's only a little modified from an answer here C++ Singleton design pattern):
class Logger
{
public:
// Returns static instance of Logger.
static Logger& getInstance()
{
static Logger logger; // This is where the assertion raises.
return logger;
}
void logError(std::string errorText);
// Destructor.
~Logger();
private:
std::ofstream logFileStream;
// The constructor is private to prevent class instantiating.
Logger();
// The copy constructor and '=' operator need to be disabled.
Logger(Logger const&) { };
Logger& operator=(Logger other) { };
};
And the constructor is:
Logger::Logger()
: logFileStream(Globals::logFileName, std::ios_base::trunc)
{
// (Tries to open the file specified in Globals for (re)writing.)
}
I found out that I can solve it by using static variables or methods somehow, but I don't understand what's wrong with this code. Does anyone know, where the problem is?
EDIT: FYI, the failure raises when this code is called (for the first time):
Logger::getInstance().logError("hello");
EDIT 2: This is the definition of logFileName in Globals:
static const std::string logFileName = "errorLog.log";
My guess is that you're calling getInstance() from the constructor of another global variable, and encountering the infamous initialisation order fiasco - it's unspecified whether or not Globals::logFileName has been initialised before any globals in other translation units.
One fix is to use an old-school C string, which will be statically initialised before any global constructor is called:
static const char * logFileName = "errorLog.log";
Another possibility is to access it via a function:
static std::string logFileName() {return "errorLog.log";}
My favoured solution would be to remove the global instance altogether, and pass a reference to whatever needs it; but some might find that rather tedious, especially if you already have a large amount of code that uses the global.
C++/CLI is not standard C++ and plays by slightly different rules. Are you using C++/CLI managed code at all? (/clr compiler option?) This looks like a common problem when mixing C++ (unmanaged) code with C++/CLI (managed) code. It has to do with the way managed and unmanaged construction and destruction happens at program initialization and program exit. Removing the destructor works for me - can you do that in your Logger class?
For more details and possible workarounds:
http://www.codeproject.com/Articles/442784/Best-gotchas-of-Cplusplus-CLI
http://social.msdn.microsoft.com/Forums/vstudio/en-US/fa0e9340-619a-4b07-a86b-894358d415f6/crtisvalidheappointer-fails-on-globally-created-object-within-a-static-llibrary?forum=vcgeneral
http://forums.codeguru.com/showthread.php?534537-Memory-leaks-when-mixing-managed-amp-native-code&p=2105565

How to pass or make public variables or fields accessible to Tthread?

I am writing and building my software for Mono using Delphi Prism. So, I decided that my serial communication will be handled by a thread. Since global variables strictly are not allowed unless you enable the global variable option for the project, I decided to follow the Delphi Prism convention. So, then how do you pass or make the public variables or fields accessible to a thread?
Here is my test mainform code:
MainForm = partial class(System.Windows.Forms.Form)
private
method SignalBtn_Click(sender: System.Object; e: System.EventArgs);
method CommBtn_Click(sender: System.Object; e: System.EventArgs);
method button1_Click(sender: System.Object; e: System.EventArgs);
method button2_Click(sender: System.Object; e: System.EventArgs);
method button4_Click(sender: System.Object; e: System.EventArgs);
method button5_Click(sender: System.Object; e: System.EventArgs);
method MainForm_Load(sender: System.Object; e: System.EventArgs);
method ShutdownBtn_Click(sender: System.Object; e: System.EventArgs);
method MySerialData(sender: System.Object; e:SerialDataReceivedEventArgs);
method LoginBtn_Click(sender: System.Object; e: System.EventArgs);
protected
method Dispose(disposing: Boolean); override;
public
RX:Array[0..5] of byte;
TX:Array[0..6] of byte;
serialPort1:System.IO.Ports.SerialPort;
thr:Thread;
stoploop:Boolean;
mcommand:Byte;
thechannel:Integer;
constructor;
method FillTable;
end;
Here is the Thread for serial communication:
ThreadComm = class(MainForm)
public
class procedure mythread; static;
end;
Here is how ThreadComm runs:
class procedure ThreadComm.mythread;
begin
while true do
begin
TX[0]:=$FF;
TX[1]:=$01;
TX[2]:=$01;
TX[3]:=$04;
TX[4]:=$A2;
TX[5]:=(TX[2] xor TX[3] xor TX[4]);
SerialPort1.Write(TX,0,6);
while SerialPort1.BytesToWrite>0 do;
Thread.Sleep(100);
if (stoploop) then
break;
end;
end;
Every time I compile the code, it raises 30 or so similar error messages stating the following:
Cannot call instance member "SerialPort1" without an instance reference
I know what the error means, but the only way to solve it is by creating an instance of the mainform. If you do that, then it won't be the same instance as the main program's instance. If this is the case, then you will have to create new instance of mainform all the time when you need to access its fields or public variables. Right?
class method Program.Main(args: array of string);
begin
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += OnThreadException;
**using lMainForm := new MainForm do
Application.Run(lMainForm);**
end;
I want to use all them variables are in the thread and they happen to be within the mainform public area.
Thanks
Your thread procedure (class procedure mythread; static;) seems to be "static" or "class", while the the fields you want to access are regular fields of a MainForm instance. That can't work, because there's one and only one procedure mythread, but there may be multiple instances of MainForm. While in practice there will probably only be one instance of MainForm, the compiler doesn't know that.
You should start by removing both class prefix and static sufix from that procedure, to make it a regular instance procedure, that can read instance fields. Even that's not going to be enough, because you derived from your MainForm, and I assume you create a new instance of ThreadCom and start the thread: Once you make the method a regular instance method the code will compile, but the result isn't going to be the one you expect, because you'll be accessing members of a different instance of MainForm.
Solutions:
Make the mythread procedure a instance method of your MainForm. It'll gain access to all required fields and access them from the proper instance!
Follow Rob's suggestion: create a new class, not derived from MainForm, pass it an instance of MainForm in the constructor, you that from the thread procedure. You'll (again) need to avoid static/class fields and procedures, because those can't be linked to one instance of MainForm.
Pass the things your thread needs as parameters to its constructor. Store references to those objects as fields in your thread class. Use them while your thread runs.
And don't make your thread class a descendant of your main form. That makes no sense. If your thread needs access to the entire form, then pass a MainForm reference to the thread's constructor. But if all your thread needs is a serial-port object, then just pass that, not the entire form.
Do not create additional instances of MainForm. That will create more forms; it won't give you access to the field values of your real main form.

Inheritance problems in TThread, don't appear to work the same in D2010 as D7

In my Application I have two thread objects (Outer and Sash) that inherit from a base thread object (FrameObject) of type TThread. This all works fine in D7. The application needs to be extended and I am taking this opportunity to move it to D2010 - however when I try to compile Delphi complains that the FrameObject Create method declaration differs from the previous declaration.
The Class types and Constructors are shown below;
TFrameObject = class(TThread)
constructor TFrameObject.Create(BuildType: TBuildType; OnBatchStep: TBatchNotify; OnThreadComplete: TNotifyTermination);
begin
inherited Create(True);
...
end;
TOuter = class (TFrameObject)
constructor Create(BuildType: TBuildType; OnBatchStep: TBatchNotify; OnThreadComplete: TNotifyTermination; ExceptionHandler: TExceptionHandler);
begin
inherited create(BuildType, OnBatchStep, OnThreadComplete);
fExceptionHandler := ExceptionHandler;
...
end;
TSash = class (TFrameObject)
constructor Create(BuildType: TBuildType; OnBatchStep: TBatchNotify; OnThreadComplete: TNotifyTermination; ExceptionHandler: TExceptionHandler);
begin
inherited create(BuildType, OnBatchStep, OnThreadComplete);
fExceptionHandler := ExceptionHandler;
...
end;
The D2010 code is a direct copy of the D7 source files and as I say, this all works fine in D7 (perhaps it shouldn't!) - so where am I going wrong?
Check for types declared in multiple units where one of them is used in the interface and another in the implementation section, so for example TBuildType in your TFrameObject declaration (in the interface section) would resolve to UnitA.TBuildType and implementation to UnitB.TBuildType.
My guess at to what is happening here is that the uses clause in your implementation section is declaring a TBuildType, TBatchNotify or TNotifyTermination that is different from the one used in your interface section where you declare the constructor.
A quick way to check would be to fully qualify those types in the implementation of TFrameObject.Create.
As per other answers, a newly introduction type in a unit used in the implementation section hiding a type of the same name used or declared in the interface section is the most likely explanation.
However, unlike previous answers, since the problem only occurs in D2010 and not D7 then I would suspect the ExceptionHandler parameter of type TExceptionHandler, since D2010 includes a type with this name declared in ToolsAPI\IStreams.
You could qualify the name in the implementation section:
TFrameObject.Create(... ExceptionHandler: MyUnit.TExpectionHandler)
Where "MyUnit" is the name of the unit containing the "real" TExceptionHandler that you wish to use.
Or, you could alias the type in the interface section and change your parameter lists to consistently use the aliased type in both interface and implementation of this unit:
interface
type
TFrameExceptionHandler = TExceptionHandler;
TFrameObject = class...
...
constructor Create(... ExceptionHandler: TFrameExceptionHandler);
end;
implementation
constructor TFrameObject.Create(... ExceptionHandler: TFrameExceptionHandler);

Resources