I have in the past written up a few tips for converting a Delphi.NET project to Delphi Prism but this time I thought it might be useful for me to write up my experiences on converting this C# Project to Delphi Prism by initially using the C#ToPas Tool from RemObjects. Many of you who attended CodeRage III (in a virtual manner) might remember Jim McKeeth‘s Revenge of Delphi Robot rage session. The aim of the session was to build a Unreal Tournament 3 Bot to fight it out against other competitor’s bots in an Unreal Tournament 3 arena using the (then) newly recently Delphi Prism tool. For those who didn’t attend, I’ll spoil the ending and just tell you that somehow my bot won. 😉

Jim is planning another session for the DelphiLive conference (which I really wish I could go to, check it out if you haven’t already). However when running the last tournament we encountered a number of fatal bugs in the .NET UT3 Bot library which was originally put together by Andy Sterland & James Lissiak. As a result Jim and I had been discussing the idea of porting the original library to Delphi Prism so that we could fix a few of the more serious bugs, it would also allow potential Prism Developers who were not familiar with C# to dig into the library itself. This is a project conversion diary which will outline the approaches I tried, any hurdles I encountered and a few tips for trying to avoid them when converting your own project.

I started by running the C#ToOxygene Tool on all of the source files within the project, It’s a very simple and easy to use tool that as its name implies aims to convert C# source files to Delphi Prism files. I was able to run the tool without issue on every C# source file except for 3 where for some reason it exited producing the error:  “Error during processing: Index was out of range” (Issue logged (rather clumsily) as #37).

Having started on the basics of the translation using the conversion tool to do the grunt work I then dived into the code with the Prism Wiki and MSDN C# documentation open to make a start on correcting the 600-odd errors that the resulting project produced upon an attempted Build.

At first glance I felt that the resultant code was a little bit visually “messy” in places and I felt it might be easier to prettify the code using a Code Formatter such as the JEDI Code Format tool to clean up the auto generated code and highlight any mismatched parenthesis or similar errors. However unfortunately the JEDI tool is not compatible with Prism and therefore refused to help me. If anyone knows of a Code Formatting tool which is compatible with Delphi Prism then please let me know in the comments below.

A few other issues which I encountered with the generated code or more generally are outlined below:

Internal Keyword

The C# internal (msdn doc) keyword was not correctly translated – for this I took a trip to the Prism Wiki and looked up the Class Member Visibility Levels page to find that the equivalent level assembly is listed there (Issue #42). Note that in Delphi Prism you can also have assembly or protected or assembly and protected depending upon whether you wish the class to be visible to descendants.

The C# “this” Keyword

The C# this. (msdn doc) keyword was not correctly translated to the Delphi Prism Self. equivalent that we’re all accustomed to. This isn’t hard to spot when going through the generated code and the issue had already been logged by Anton Kasyanov (Issue #39) and should be fixed shortly.

Float Types

One class made extensive use of the float type (msdn doc) which doesn’t exist as is a built-in type for Delphi Prism so you’ll need to convert it to one of the two Float types depending upon the precision you require.

Operator Overloading

Operator Overloading is not something that Delphi developers may be traditionally used to but Delphi Prism supports this nicely. However instead of using the sign operator that C# Developers use you’ll need to lookup the operator name and declaration on the Operator Overloading Wiki Page. eg. The Equals operator is declared as so:

class operator Equal(obj1, obj2: UTIdentifier): boolean;

Differences between return, Result and exit

This should be obvious to any C# Developer but it could be easy to forget about. Don’t forget that the return C# method (msdn doc) terminates execution of the method in which it is being executed and returns to the calling method and therefore be wary of using Result blindly in an identical manner, particularly with boolean statements that rely upon this fact. Eg. Consider the following C# Code:

public override bool Equals(object obj)
	if (obj is UTVector)
		if (this._x == ((UTVector)obj)._x &&
			this._y == ((UTVector)obj)._y &&
			this._z == ((UTVector)obj)._z)
			return true;
	return false;

Clearly, if you simply replace the return false; with Result := False; you will end up with a method that always returns False because the expression will always be executed no matter what Result is set to earlier in the method. In this case I simply moved the Result := false; to the top of the method. Delphi Prism also supports the Exit keyword which also allows you to Return a result parameter. This method is a lot closer to the C# return keyword and usage but the Exit page on the Prism Wiki warns against using too many exit keywords to avoid making the code harder to maintain.

Constructors are not named

This is a rare example of where the original C# code actually looks much closer to the end Delphi Prism code than a traditional Delphi programmer might think. In C# you might have a class and constructor that might look like this:

public class UTIdentifier
	internal UTIdentifier(string Id)

In Prism, we have nameless constructors which means that the equivalent Delphi Prism constructor implementation might look like this:

  constructor UTIdentifier(id: String);

It is important to note that in your class interface should adhere to this rule too. eg constructor(id: String);

This was something that the C#ToPas tool also generated incorrectly. (Issue #44)

Short-Circuit Boolean Expressions

I came across the C# || operator which performs a short-circuited OR boolean evaluation of the operands. I wasn’t sure that the Delphi Prism or operator produces the same behaviour but if I read the Expression Evaluation page correctly then I believe it does (In Delphi 2009, at least, this behaviour is set through the {$B+/-} compiler flag) .

Event Assignment

The Event Assignment routine for multicast delegate type events is slightly different in Delphi Prism from what we’re used to in Delphi Win32. Looking at the Event Assignment page in the wiki we can see that the actual method for assignment is much closer to the C# equivalent and uses the same C# += and -= operators. The C#ToPas tool converted this code a little too literally converted this C# code:

this._connection.OnDataReceived += new EventHandler(DataReceived);
this._connection.OnErrorOccurred += new EventHandler(ErrorOccurred);

to this:

Self._connection.OnDataReceived := Self._connection.OnDataReceived + new EventHandler(DataReceived);
Self._connection.OnErrorOccurred := Self._connection.OnErrorOccurred + new EventHandler(ErrorOccurred)

Which produces a compiler Error that Events in Delphi Prism don’t allow access to the underlying field. You should use the += operator instead as seen on the Wiki. (C#ToPas Issue logged as Issue #45).

UPDATE: I’ve just noticed (after logging my own issue) that the event assignment issue has already been reported and has been marked as Won’t Fix (Issue #27) so it looks like you’ll need to check _every_ event assignment in your project manually.

Switch and Case Statements

The C#ToPas tool did not appear to react well at all to use of the C# switch and case statements. I can’t give you any specific advice on how to fix these because each case statement was generated slightly differently in my converted code and therefore I can only advise that you check these manually or rewrite each of these methods by hand.

Reserved Keywords

Sadly this isn’t an issue that is related to the C#ToPas tool but more of an intrinsic difficulty when converting interoperable code between languages. I encountered at least one class that made use of a few reserved words in Delphi such as begin and end – I’m still not sure what to do with these for now.

Overall Impression

Despite a few early bugs the C#ToPas Tool is a good platform to begin converting your C# code to Delphi Prism although you may wish to ensure that you have some extensive Unit Tests for your code before the main code is converted so as to ensure that any bugs introduced can be picked up on quickly (which you have anyway right?). It is also worth noting that the Delphi Prism Wiki (which now authenticates via your CDN login) has excellent coverage and is an absolutely invaluable reference for anyone working with Delphi Prism.

By the time this entry is published I suspect that Carlo will be very close to fixing some or most of the above bugs in the C#ToPas tool.

The code is nowhere near complete yet and most of the files are still straight out of the Automatic conversion and therefore will not compile in any way but I’ve put what we have so far up on the rather smooth Github site at the PrismUT3RemoteBot project which anyone can fork and push changes back to. Git is a little strange to work with at first because it’s a different mindset to SubVersion/CVS but it’s worth checking out if you haven’t already.

[UPDATE: The Prism UT3 Remote Bot conversion project has been completed since this original post and may be used during Jim McKeeth’s session at DelphiLive! Germany Sept 28 – Oct 2 2009.]

Tags: , ,

One Comment

  1. Anibal on the 22nd June 2011 remarked #

    In this moment hate Delphi Prism…

Leave a Comment