Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2007-01

Linking to C++

55 messages · 20 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Felipe Monteiro de Carvalho

Hello,

I was studing how to write the system unit for Symbian OS, and everything on Symbian is C++, so you actually import lot´s of methods from classes, not procedures. So I decided to study the task of linking from Free Pascal to C++

Maybe it´s easy to be implemented, and that would be very nice. Here is my test:

To start with I created a trivial C++ DLL:

File: cpplib.cpp

class User
{
public:

     __declspec(dllexport) int Sum(int a, int b);

};

int User::Sum(int a, int b)
{

    return a + b;

}

File: build.bat

PATH=C:\Programas\Dev-Cpp\bin
g++ -c cpplib.cpp -o cpplib.o
dllwrap.exe --output-def cpplib.def --driver-name c++ --implib cpplib.a cpplib.o -L"c:/Programas/dev-cpp/lib" --no-export-all-symbols --add-stdcall-alias -o cpplib.dll

Calling build.bat will of course produce cpplib.dll It also produces a cpplib.def

Now, I utilized dllview software I created and saw that cpplib exports this function: _ZN4User3SumEii

Then, I created a simple pascal software to call that function:

program loadcpp;
{$mode objfpc}{$H+}
{$apptype console}
uses
  SysUtils, ctypes;
function User_Sum(Self: Pointer; a, b: cint): cint; cdecl; external
'cpplib.dll' name '_ZN4User3SumEii';
begin
  WriteLn('7 + 8 = ' + IntToStr(User_Sum(nil, 7, 8)));
end.

And it works!

So, basically, what I mean with this is: What is needed to add C++ linking to Free Pascal? It seams to me that it should be easy, we just need to understand C++ name mangling and choose a sintax to implement it. Maybe something like this:

type
  User = class
  public:
    function Sum(a, b: cint): cint; cdecl; external 'cpplib.dll';
cpp_name_mangling;
  end;

One possible problem is C++ multiple inheritance. I would propose that, to start with, just disconsider it.

Disclaimer: I know very little on the subject, so feel free to correct me =)

thanks,

Felipe Monteiro de Carvalho

Reply by email

Peter Popov
to Felipe Monteiro de Carvalho

The simple answer is that you cannot reliably mix object oriented langugages without severe portability issues and without loosing basic functionality: polymorphism. You simply cannot extend the functionality of a class written in one language from another language.

ON THE LINKING PART: all that distinguishes a member function from a usual one is that a member function has an implicit first argument which is a pointer to the class instance. So, you can put all your member functions in a dll, and from an assembly level view point they are just regular function with an additional first argument (pointer to the class instence
- *this in c++, self in o-pascal). How the calling language interprets them is a matter of the calling language.

The problem is the logical structure of a class. That is, the layout of the VMT, and stuff like this. Generally, the pointer to the first virtual method is at offset 0, so you can safely call virtual functions from a single inherited C++ class. However, everything else is different. For example, different versions of delphi place the automated methods at a different offset, etc. The simplest problem is the destrictor. All delphi classes have the destructor at offset -4. A C++ class CANNOT have a virtual destructor (the VMT is killed when you call delete, before the class' destructor is called). In fact, C++ classes need not have a VMT at all.

So if the function calls virtual methods, the dll that contains that function MUST use the internal representation of a class as the calling program (which supplies *this, e.g. Self). This will force you to use the same object model as C++. Since C++ does not support class functions for example, I don't see how you can mix a delphi function in a dll with C++ code. A C++ class need not have a a C++ member function belongs to a Multiple Inheritance class then this class will have several VMTs, so the whole thing becomes pointless. You cannot ensure any code portability. So linking is not the problem.

If you want to use class libraries, you have to make this class library into a reasonable API with reasonable semantics, behavior and so on. An example is the way QT is interfaced with Kylix. It works, only because QT is reasonably well written, all the new/deletes of QT objects are explicitly wrapped in Kylix, and the published QT member functions don't do weird things. All QT functions are wrapped as normal function, by explictly specifying the Self pointer as the first argument. The last problem in this is the actual linking. In fact the unofficial QT patches (QT 3) does the same thing using object semantics on the Kylix side. It works, because QT is a reasonable API, and obviously, you cannot extend QT in any way.

I don't know what FPC does with member functions, but Delphi does not export them. You cannot put a member function in the export part of a library. You have to create a wrapper (normal function with Self as the first argument) and then export the wrapper. So, if you happen to have a good class API in Delphi, you have to manually type wrappers and export them. This can be changed in FPC by allowing TMyObject.MyFunction in the export part of a library.

Peter

Felipe Monteiro de Carvalho wrote 78 lines
Hello, I was studing how to write the system unit for Symbian OS, and everything on Symbian is C++, so you actually import lot´s of methods from classes, not procedures. So I decided to study the task of linking from Free Pascal to C++ Maybe it´s easy to be implemented, and that would be very nice. Here is my test: To start with I created a trivial C++ DLL: File: cpplib.cpp class User { public: __declspec(dllexport) int Sum(int a, int b); }; int User::Sum(int a, int b) { return a + b; } File: build.bat PATH=C:\Programas\Dev-Cpp\bin g++ -c cpplib.cpp -o cpplib.o dllwrap.exe --output-def cpplib.def --driver-name c++ --implib cpplib.a cpplib.o -L"c:/Programas/dev-cpp/lib" --no-export-all-symbols --add-stdcall-alias -o cpplib.dll Calling build.bat will of course produce cpplib.dll It also produces a cpplib.def Now, I utilized dllview software I created and saw that cpplib exports this function: _ZN4User3SumEii Then, I created a simple pascal software to call that function: program loadcpp; {$mode objfpc}{$H+} {$apptype console} uses SysUtils, ctypes; function User_Sum(Self: Pointer; a, b: cint): cint; cdecl; external 'cpplib.dll' name '_ZN4User3SumEii'; begin WriteLn('7 + 8 = ' + IntToStr(User_Sum(nil, 7, 8))); end. And it works! So, basically, what I mean with this is: What is needed to add C++ linking to Free Pascal? It seams to me that it should be easy, we just need to understand C++ name mangling and choose a sintax to implement it. Maybe something like this: type User = class public: function Sum(a, b: cint): cint; cdecl; external 'cpplib.dll'; cpp_name_mangling; end; One possible problem is C++ multiple inheritance. I would propose that, to start with, just disconsider it. Disclaimer: I know very little on the subject, so feel free to correct me =) thanks,

|***********************************************|

Reply by email

Daniël Mantione
to Felipe Monteiro de Carvalho: I was studing how to write the system unit for Symbian OS, and everything on Symbian is…

Op Mon, 22 Jan 2007, schreef Felipe Monteiro de Carvalho:

So, basically, what I mean with this is: What is needed to add C++ linking to Free Pascal? It seams to me that it should be easy, we just need to understand C++ name mangling and choose a sintax to implement it. Maybe something like this:

If it were that easy it would have been implemented a long time ago. The main problem with C++ is that the supporting structures, such as the VMT are totally different from Pascal. One of the reasons is that multiple inheritance needs to be supported in C++. Of the problems, that will for example occur, is to call a virtual C++ method, this needs VMT access, which the compiler cannot provide.

Of course, you can import a class like you did, and even automate it, I don't see a problem with adding C++ mangling. But, you cannot use class syntax, since classes are fundamentally incompatible with C++ classes.

Daniël

Reply by email

Peter Popov
to Felipe Monteiro de Carvalho: I was studing how to write the system unit for Symbian OS, and everything on Symbian is…

Further reading on some limited portability of C++ classes into Delphi:

http://www.rvelthuis.de/articles/articles-cppobjs.html

Take a specific look at the second part, with pure virtual classes. The trouble is it only works for virtual C++ classes (have at least on virtual function - hence a VMT) with single inheritance (single VMT with virtual functions at offset 0). The C++ dll must provide a factory function and a wrapper for deleting the class. No further extension of this class is possible in Delphi.

Felipe Monteiro de Carvalho wrote 78 lines
Hello, I was studing how to write the system unit for Symbian OS, and everything on Symbian is C++, so you actually import lot´s of methods from classes, not procedures. So I decided to study the task of linking from Free Pascal to C++ Maybe it´s easy to be implemented, and that would be very nice. Here is my test: To start with I created a trivial C++ DLL: File: cpplib.cpp class User { public: __declspec(dllexport) int Sum(int a, int b); }; int User::Sum(int a, int b) { return a + b; } File: build.bat PATH=C:\Programas\Dev-Cpp\bin g++ -c cpplib.cpp -o cpplib.o dllwrap.exe --output-def cpplib.def --driver-name c++ --implib cpplib.a cpplib.o -L"c:/Programas/dev-cpp/lib" --no-export-all-symbols --add-stdcall-alias -o cpplib.dll Calling build.bat will of course produce cpplib.dll It also produces a cpplib.def Now, I utilized dllview software I created and saw that cpplib exports this function: _ZN4User3SumEii Then, I created a simple pascal software to call that function: program loadcpp; {$mode objfpc}{$H+} {$apptype console} uses SysUtils, ctypes; function User_Sum(Self: Pointer; a, b: cint): cint; cdecl; external 'cpplib.dll' name '_ZN4User3SumEii'; begin WriteLn('7 + 8 = ' + IntToStr(User_Sum(nil, 7, 8))); end. And it works! So, basically, what I mean with this is: What is needed to add C++ linking to Free Pascal? It seams to me that it should be easy, we just need to understand C++ name mangling and choose a sintax to implement it. Maybe something like this: type User = class public: function Sum(a, b: cint): cint; cdecl; external 'cpplib.dll'; cpp_name_mangling; end; One possible problem is C++ multiple inheritance. I would propose that, to start with, just disconsider it. Disclaimer: I know very little on the subject, so feel free to correct me =) thanks,
|***********************************************| | | | Peter Popov, | | | | 608N Blocker Bldg. | | Institute for Scientific Computation, | | Texas A&M University | | College Station, Texas 77843-3404 | |-----------------------------------------------| | Phone: +1 (979) 458-4644, | | Fax: +1 (979) 845-5827 | | | |***********************************************|

Reply by email

Felipe Monteiro de Carvalho
to Daniël Mantione: Op Mon, 22 Jan 2007, schreef Felipe Monteiro de Carvalho: If it were that easy it would…
I don't know what FPC does with member functions, but Delphi does not

export them. You cannot put a member function in the export part of a library. You have to create a wrapper (normal function with Self as the first argument) and then export the wrapper. So, if you happen to have a good class API in Delphi, you have to manually type wrappers and export them. This can be changed in FPC by allowing TMyObject.MyFunction in the export part of a library.

That would be nice!

But would would be the inverse of exporting a method?

Maybe this:

type
 User = class
 public:
   function Sum(a, b: Integer): Integer; external 'mylib.dll';
 end;

being that Sum is a method created on a object pascal library.

Daniël Mantione wrote
Of course, you can import a class like you did, and even automate it, I don't see a problem with adding C++ mangling. But, you cannot use class syntax, since classes are fundamentally incompatible with C++ classes.

Automating C++ mangling would already be great, but if one can´t use c++ methods inside classes, how will the name mangler know that the function is actually a method from a class with a given name?

And how would this be added? Extra keywords to be added to functions? Maybe 2 different keywords, one for cpp method name mangling and another for c function name mangling, so I would declare:

function User.Sum(Self: Pointer; a, b: cint): cint; cdecl; external
'cpplib.dll'; cpp_method_name_mandling;

On this solution we treat the C++ object as a pointer that is passed around, and can only be created and destroyed by imported functions.

Felipe Monteiro de Carvalho

Reply by email

Felipe Monteiro de Carvalho
to Peter Popov: Further reading on some limited portability of C++ classes into Delphi:…
Peter Popov wrote 6 lines
Take a specific look at the second part, with pure virtual classes. The trouble is it only works for virtual C++ classes (have at least on virtual function - hence a VMT) with single inheritance (single VMT with virtual functions at offset 0). The C++ dll must provide a factory function and a wrapper for deleting the class. No further extension of this class is possible in Delphi.

Althougth something really nice to know, this is unusable for my specific case, because I didn´t write the Symbian OS DLLs, and I also don´t want to require pascal software to be distributed with a special DLL on symbian (which would contain the factory function).

Felipe Monteiro de Carvalho

Reply by email

Den Jean
to Felipe Monteiro de Carvalho: I was studing how to write the system unit for Symbian OS, and everything on Symbian is…
Felipe Monteiro de Carvalho wrote 5 lines
Hello, Now, I utilized dllview software I created and saw that cpplib exports this function: _ZN4User3SumEii

IIRC C++ compiler/platform dependant.
So do not use this to be compiler independant
GCC even changed its name mangling in between versions.

Show quoted text 8 lines
Then, I created a simple pascal software to call that function: program loadcpp; {$mode objfpc}{$H+} One possible problem is C++ multiple inheritance. I would propose that, to start with, just disconsider it.

AFAIK the class that inherits from multiple classes, is actually just several classes with several vtables. To be able to use it from pascal, the self pointer in

    function User_Sum(Self: Pointer; a, b: cint): cint; cdecl; external

should be different depending on which vtable you want to call.

http://www.freepascal.org/wiki/index.php/Qt4_binding#C.2B.2B_Multiple_inheritance

implementation of QWidget_to_QPaintDevice:
QPaintDeviceH QWidget_to_QPaintDevice(QWidgetH handle) {

		return (QPaintDeviceH)(QPaintDevice *)(QWidget *)handle;
	}

the typecast (QPaintDevice *) turns the number (QWidget *)handle into another number, pointing to another vtable.

But again this is compiler/version dependant reading the following: http://gcc.gnu.org/ml/gcc-patches/2000-01/msg00620.html

regards,

Den Jean

Reply by email

Daniël Mantione
to Felipe Monteiro de Carvalho: export them. You cannot put a member function in the export part of a library. You have…

Op Mon, 22 Jan 2007, schreef Felipe Monteiro de Carvalho:

Show quoted text 18 lines
On 1/22/07, Daniël Mantione wrote: > Of course, you can import a class like you did, and even automate it, I > don't see a problem with adding C++ mangling. But, you cannot use class > syntax, since classes are fundamentally incompatible with C++ classes. Automating C++ mangling would already be great, but if one can´t use c++ methods inside classes, how will the name mangler know that the function is actually a method from a class with a given name? And how would this be added? Extra keywords to be added to functions? Maybe 2 different keywords, one for cpp method name mangling and another for c function name mangling, so I would declare: function User.Sum(Self: Pointer; a, b: cint): cint; cdecl; external 'cpplib.dll'; cpp_method_name_mandling; On this solution we treat the C++ object as a pointer that is passed around, and can only be created and destroyed by imported functions.

It will have to be done like this: Treat the self pointer as some kind of handle. The handle is created by the constructor and destroyed by the destructor. Calling virtual methods is not possible, in fact OOP programming is not possible due to the lack of polymorphy; you will interface with the C++ library completely with procedural programming.

Daniël

Reply by email

Den Jean
to Peter Popov: The simple answer is that you cannot reliably mix object oriented langugages without…
Peter Popov wrote 5 lines
example is the way QT is interfaced with Kylix. It works, only because QT   is reasonably well written, all the new/deletes of QT objects are   explicitly wrapped in Kylix, and the published QT member functions don't   do weird things. All QT functions are wrapped as normal function, by   explictly specifying the Self pointer as the first argument. The last  

Qt even documented a LSB ABI for their toolkit (platform specific)

http://www.linux-foundation.org/en/Specifications#LSB_Qt_4

The IA32 platform:
http://refspecs.freestandards.org/LSB_3.1.0/Toolkit_Qt4-IA32/Toolkit_Qt4-IA32/libqtcore.html

Reply by email

Felipe Monteiro de Carvalho
to Den Jean

Maybe the compiler could hide the
procedurization/re-object-orientation, thus making interfacing easier.

So this:

type
 User = class
 public
   function Sum(a, b: cint): cint; cdecl; external 'cpplib.dll';
 end;

Would be the exact equivalent of:

function User_Sum(Self: Pointer; a, b: cint): cint; cdecl; external
'cpplib.dll' name '_ZN4User3SumEii';
type
 User = class
 private
    InternalHandle: Pointer;
 public
   function Sum(a, b: cint): cint; cdecl;
 end;
function User.Sum(a, b: cint): cint;
begin
  Result := User_Sum(InternalHandle, a, b);
end;
Felipe Monteiro de Carvalho

Reply by email

Felipe Monteiro de Carvalho
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote
Maybe the compiler could hide the procedurization/re-object-orientation, thus making interfacing easier.

Basically this would be nice for me because the Symbian OS headers are incredibly huge. There more then 100.000 lines of .h files in there ...

Actually probably much more. There are 10 MB of .h files

And using proceduralization / re-object-orientation manually would result on something even much larger, perhaps 2 times larger or more.

Felipe Monteiro de Carvalho

Reply by email

Felipe Monteiro de Carvalho
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote
And using proceduralization / re-object-orientation manually would result on something even much larger, perhaps 2 times larger or more.

Just to avoid mis-interpretation. It´s not only a question of saving lines of code, but also of readability and maintenance.

Felipe Monteiro de Carvalho

Reply by email

Peter Popov
to Felipe Monteiro de Carvalho: Maybe the compiler could hide the procedurization/re-object-orientation, thus making…

About the name mangling: this thing is compiler specific. To have really portable code, whoever compiled the DLL should include flattened procedural API model without name mangling. See the Kylix QT libraries: borland have compiled their own version of Qt2.3.0 and have exported things in a portable fashion. As things should be done.

Now, there is now way to extend an already compiled C++ class, so whoever did the DLL MUST PROVIDE factory constructor and destructor. There is now way to mix the construction and destruction of classes (C++ and Pascal VMTs are different). So, a single member function cannot be exported alone. You have to export all members of the entire class. Therefore, the DLL creator should provide a flattened interface + constructor and destructor wrappers. This may, or may not be done automatically by the compiler. It is a matter of choice. Look here
http://andy.jgknet.de/oss/kylix/wiki/index.php/Qt3Clx for some enthisiasts who apparently interfaced kylix with QT3 in some automatic fasion.

However, the DLL creator MUST RID THE EXPORT TABLE OF MANGLED NAMES. Mangled names are just not portable: consider the idiots who maintain the gcc standard libraries on linux. I have a lingering suspicion that these morons itentionally make the binaries incompatible from version to version. This way they force everybody to recompile their SOURCE CODE against the new gcc libraries version. Moreover, they force C++ programmers to use gcc, when compiling complex programs under linux. This prevents people from the distribute and forget model of supplying binaries. You simply have to maintain whatever program you compiled against gcc. This is why you cannot write some nice variant of solitaire, distribute and forget about it. The next major version of QT will break it. So essentially, a fully portable API should treat the class instances as "Handles" (e.g. win32, libborqt.so) and you use them as standard functions. The code on the back side may or may not use classes, but the front end is always transparent. So, unfortunately, the only thing you can do is file a complaint with whoever is maintaining this Symbian API.

Peter

PS. If a library forces you to mix objects in different languages, it simply is a badly written library.

Felipe Monteiro de Carvalho wrote 29 lines
Maybe the compiler could hide the procedurization/re-object-orientation, thus making interfacing easier. So this: type User = class public function Sum(a, b: cint): cint; cdecl; external 'cpplib.dll'; end; Would be the exact equivalent of: function User_Sum(Self: Pointer; a, b: cint): cint; cdecl; external 'cpplib.dll' name '_ZN4User3SumEii'; type User = class private InternalHandle: Pointer; public function Sum(a, b: cint): cint; cdecl; end; function User.Sum(a, b: cint): cint; begin Result := User_Sum(InternalHandle, a, b); end;

Reply by email

Jason P Sage

Hello All,

This may have been mentioned with different words already - but I'm getting the impression one should write a "C++ handler API" or "thin layer" for the C++ lib one wants to utilize. The idea being FPC would only link on standard calls that more or less ran the underlying C++ lib like a remote control car (if that makes sense). On the FPC side you would tell the "thin layer" what objects to make, and allow for passing information to and from individual instances of classes within the "thin client", and invoking methods the same way.

This doesn't seem ideal by any stretch of the imagination - and makes me think of ugly things in time's past like 32bit to 16bit "thunking", but this kind of "thin layer" coding (an API ultimately) seems like it MAY be the best way to link to the various libraries out there. I'm thinking of gcc and Microsoft API's generally.

Personally - regardless of the difficulties - I've had some pretty decent luck with FPC and using the headers that people have created for various libraries that are crucial - like mysql and odbc. If I had more time to mess around I'd be playing with Direct X and Open GL too. Regardless - I'm happy with it so far!

I welcome any and all comments.

Good Day
Jason P Sage

No virus found in this outgoing message. Checked by AVG Free Edition. Version: 7.5.432 / Virus Database: 268.17.4/643 - Release Date: 1/21/2007 5:12 PM

Reply by email

Thorsten Engler
to Jason P Sage

While playing around with the compiler source to familiarize myself I've produced the attached patch. While I didn't set out to produce anything for inclusion into the official codebase at least some of the changes might be generally useful.

a) now modeswitch: m_ident_escape

Allows escaping of identifiers which might otherwise be recognized as keywords. This mirrors Delphi's (and Chrome's) implementation.

type
  TMyRecord = record
    &unit: Integer;
  end;

No space is allowed betweehn & and identifier. As identifiers are not allowed to start with digits there is no collision with the &123 support for base 8 integer constants.

b) new modeswitch: m_always_ident_after_dot

There are no valid cases in the pascal grammer where a keyword follows a single dot. As a) makes it now possible to declare identifiers which are identical to keywords qualified access to these fields can now be simplified by always recognizing an identifier/keyword following a dot as a simple identifier, no matter if it matches a keyword or not.

I'm not sure if Delphi implements this. Chrome does.

var
  myRecord: TMyRecord;
begin
  myRecord.unit := 123;
end;

These 2 switches should not affect compatibility to existing code. I can run a complete make all / make install with both of these generally active. It could be considered to add them to {$mode objfpc}

c) new $mode: m_chrome

Currently baseed on objfpc with the addition of all 3 new mode switches. In addition to a) and b) m_chrome allows the use of "method" as an alternative to both procedure and function (if the method is a procedure or function can simply be determined by the presence of a defined result type).

A slightly extreme example follows:

>>>
{$mode chrome}
program ChromeTest;
type
  TMyObject = class
    method Foo;
    method Bar: Integer;
    class method ClassFoo;
    class method ClassBar: Integer;
    method &class;
    method &method(&string: string):string;
  end;
type
  &method = method(&string: string):string of object;

{ TMyObject }

method TMyObject.Bar: Integer;
begin
  WriteLn('TMyObject.Bar');
  Result := 0;
end;
method TMyObject.Foo;
begin
  WriteLn('TMyObject.Foo');
end;
class method TMyObject.ClassBar: Integer;
begin
  WriteLn('TMyObject.ClassBar');
  Result := 0;
end;
class method TMyObject.ClassFoo;
begin
  WriteLn('TMyObject.ClassFoo');
end;
method TMyObject.class;
begin
  WriteLn('Class');
end;
method TMyObject.method(&string: string):string;
begin
  Result := '*** ' + &string + ' ***';
end;
method Foo;
begin
  WriteLn('Foo');
end;
method Bar: Integer;
begin
  WriteLn('Bar');
  Result := 0;
end;
var
  &object: TMyObject;
  amethod: &method;
begin
  Foo;
  Bar;
  TMyObject.ClassFoo;
  TMyObject.ClassBar;
  &object := TMyObject.Create;
  &object.Class;
  amethod := @&object.method;
  WriteLn(amethod('method'));
  with &object do try
    Foo;
    Bar;
    &class;
  finally
    Free;
  end;
end.
<<<<

Cheers,
Thorsten

Reply by email

Bogusław Brandys
to Jason P Sage: This may have been mentioned with different words already - but I'm getting the…
Jason P Sage wrote 31 lines
Hello All, This may have been mentioned with different words already - but I'm getting the impression one should write a "C++ handler API" or "thin layer" for the C++ lib one wants to utilize. The idea being FPC would only link on standard calls that more or less ran the underlying C++ lib like a remote control car (if that makes sense). On the FPC side you would tell the "thin layer" what objects to make, and allow for passing information to and from individual instances of classes within the "thin client", and invoking methods the same way. This doesn't seem ideal by any stretch of the imagination - and makes me think of ugly things in time's past like 32bit to 16bit "thunking", but this kind of "thin layer" coding (an API ultimately) seems like it MAY be the best way to link to the various libraries out there. I'm thinking of gcc and Microsoft API's generally. Personally - regardless of the difficulties - I've had some pretty decent luck with FPC and using the headers that people have created for various libraries that are crucial - like mysql and odbc. If I had more time to mess around I'd be playing with Direct X and Open GL too. Regardless - I'm happy with it so far! I welcome any and all comments. Good Day Jason P Sage

If libraries are using pure C then you are lucky.If C++ ,then the only reasonable way for me is a thin wrapper DLL(s) :-( Of course you can use perl/python or create own object parser (in FPC) to actually recognize current mangling of functions but as you know it's not enough.All depends of how C++ classes are structured.afaik Qt is using some kind of parser also but I don't know the details.

Regards
Boguslaw

Reply by email

Joost van der Sluis
to Thorsten Engler: While playing around with the compiler source to familiarize myself I've produced the…

I'm very against this (especially in mode objfpc), and I don't get the my opinion we have to keep the language as clean as possible.

What could be a rood reason to escape a keyword? Why do you as programmer insist on the use of a keyword? Why do you insist that your property is called 'unit'? It's just obfuscating the code. With this you can mangle your code completely...

(If you want to make a code-obfuscator, as they do sometimes with .php pages, yes, then I understand why you should want this.)

And about the 'method' thing... We could also replace the 'property' keyword by 'something'. Hey, we can also replace method by 'something'! Woudn't that be nice. So you get:

type
  TMyObject = class
    Fs : String;
    something Foo;
    something Bar: Integer;
    class something ClassFoo;
    class something ClassBar: Integer;
    something s : read Fs write Fs;
end;

Hmm... maye it's better to get rid off 'something' completely, then...

In short: why do ou want to get rid of the difference between 'procedure' and 'function'?

Or do I miss something completely?

Joost.

Thorsten Engler wrote 146 lines
While playing around with the compiler source to familiarize myself I've produced the attached patch. While I didn't set out to produce anything for inclusion into the official codebase at least some of the changes might be generally useful. a) now modeswitch: m_ident_escape Allows escaping of identifiers which might otherwise be recognized as keywords. This mirrors Delphi's (and Chrome's) implementation. type TMyRecord = record &unit: Integer; end; No space is allowed betweehn & and identifier. As identifiers are not allowed to start with digits there is no collision with the &123 support for base 8 integer constants. b) new modeswitch: m_always_ident_after_dot There are no valid cases in the pascal grammer where a keyword follows a single dot. As a) makes it now possible to declare identifiers which are identical to keywords qualified access to these fields can now be simplified by always recognizing an identifier/keyword following a dot as a simple identifier, no matter if it matches a keyword or not. I'm not sure if Delphi implements this. Chrome does. var myRecord: TMyRecord; begin myRecord.unit := 123; end; These 2 switches should not affect compatibility to existing code. I can run a complete make all / make install with both of these generally active. It could be considered to add them to {$mode objfpc} c) new $mode: m_chrome Currently baseed on objfpc with the addition of all 3 new mode switches. In addition to a) and b) m_chrome allows the use of "method" as an alternative to both procedure and function (if the method is a procedure or function can simply be determined by the presence of a defined result type). A slightly extreme example follows: >>>> {$mode chrome} program ChromeTest; type TMyObject = class method Foo; method Bar: Integer; class method ClassFoo; class method ClassBar: Integer; method &class; method &method(&string: string):string; end; type &method = method(&string: string):string of object; { TMyObject } method TMyObject.Bar: Integer; begin WriteLn('TMyObject.Bar'); Result := 0; end; method TMyObject.Foo; begin WriteLn('TMyObject.Foo'); end; class method TMyObject.ClassBar: Integer; begin WriteLn('TMyObject.ClassBar'); Result := 0; end; class method TMyObject.ClassFoo; begin WriteLn('TMyObject.ClassFoo'); end; method TMyObject.class; begin WriteLn('Class'); end; method TMyObject.method(&string: string):string; begin Result := '*** ' + &string + ' ***'; end; method Foo; begin WriteLn('Foo'); end; method Bar: Integer; begin WriteLn('Bar'); Result := 0; end; var &object: TMyObject; amethod: &method; begin Foo; Bar; TMyObject.ClassFoo; TMyObject.ClassBar; &object := TMyObject.Create; &object.Class; amethod := @&object.method; WriteLn(amethod('method')); with &object do try Foo; Bar; &class; finally Free; end; end. <<<< Cheers, Thorsten _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel
Met vriendelijke groeten, Joost van der Sluis CNOC Informatiesystemen en Netwerken http://www.cnoc.nl

Reply by email

Michael Van Canneyt
to Thorsten Engler: While playing around with the compiler source to familiarize myself I've produced the…
Thorsten Engler wrote 18 lines
While playing around with the compiler source to familiarize myself I've produced the attached patch. While I didn't set out to produce anything for inclusion into the official codebase at least some of the changes might be generally useful. a) now modeswitch: m_ident_escape Allows escaping of identifiers which might otherwise be recognized as keywords. This mirrors Delphi's (and Chrome's) implementation. type TMyRecord = record &unit: Integer; end; No space is allowed betweehn & and identifier. As identifiers are not allowed to start with digits there is no collision with the &123 support for base 8 integer constants.

I think this goes against all that pascal stands for. We don't want to butcher the language. Next thing you'll be asking to have it case sensitive. As a programmer you know that certain keywords are keywords. Don't use them in your fields/variables whatever. Keep you code readable.

Show quoted text 23 lines
b) new modeswitch: m_always_ident_after_dot There are no valid cases in the pascal grammer where a keyword follows a single dot. As a) makes it now possible to declare identifiers which are identical to keywords qualified access to these fields can now be simplified by always recognizing an identifier/keyword following a dot as a simple identifier, no matter if it matches a keyword or not. I'm not sure if Delphi implements this. Chrome does. var myRecord: TMyRecord; begin myRecord.unit := 123; end; These 2 switches should not affect compatibility to existing code. I can run a complete make all / make install with both of these generally active. It could be considered to add them to {$mode objfpc} c) new $mode: m_chrome

If a is not implemented, then B should not be implemented either.

Show quoted text 5 lines
Currently baseed on objfpc with the addition of all 3 new mode switches. In addition to a) and b) m_chrome allows the use of "method" as an alternative to both procedure and function (if the method is a procedure or function can simply be determined by the presence of a defined result type).

No. It obfuscates the difference between procedure and function. This is not C, but pascal.

Michael.

Reply by email

Daniël Mantione
to Michael Van Canneyt

Op Tue, 23 Jan 2007, schreef Michael Van Canneyt:

I think this goes against all that pascal stands for. We don't want to butcher the language. Next thing you'll be asking to have it case sensitive. As a programmer you know that certain keywords are keywords. Don't use them in your fields/variables whatever. Keep you code readable.

Well, there are many things in Delphi against all Pascal stands for. Yet we need it for compatibility, and despite our, IMHO totally reasonable, clean-up attempts $mode delphi might even be used more than $mode objfpc :(

I think history has shown that it is not wise to reject things. IMO, the features can be provided in a Chrome mode, while fpc and objfpc remain clean Pascal. Even that has its limits, code exchange must remain possible between fpc and non-fpc modes, but despite all the crap, we can at least try to keep them clean.

Daniël

Reply by email

Michael Van Canneyt
to Daniël Mantione
Daniël Mantione wrote 13 lines
Op Tue, 23 Jan 2007, schreef Michael Van Canneyt: > I think this goes against all that pascal stands for. We don't want to > butcher the language. Next thing you'll be asking to have it case sensitive. > As a programmer you know that certain keywords are keywords. Don't use them > in your fields/variables whatever. Keep you code readable. Well, there are many things in Delphi against all Pascal stands for. Yet we need it for compatibility, and despite our, IMHO totally reasonable, clean-up attempts $mode delphi might even be used more than $mode objfpc :(

Well, not in e.g. lazarus, and only to 'import' delphi code.

Show quoted text 5 lines
I think history has shown that it is not wise to reject things. IMO, the features can be provided in a Chrome mode, while fpc and objfpc remain clean Pascal. Even that has its limits, code exchange must remain possible between fpc and non-fpc modes, but despite all the crap, we can at least try to keep them clean.

In that case I suggest introducing a rule that all FPC provided code is fpc or objfpc or macpas (for unified pascal headers) mode.

And if we implement this, we should also introduce the foreach and whatever other insane things Borland thinks of the last years, which we refused with arguments like "it's only a typing saver". You can't sit on two chairs at once.

We should at least be consequent in our policies.

Personally, I think the foreach is even more reasonable than this. Pascal is a readable language. This proposal seriously threatens that.

Michael.

Reply by email

Thorsten Engler
to Joost van der Sluis: I'm very against this (especially in mode objfpc), and I don't get the my opinion we have…

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

What could be a rood reason to escape a keyword? Why do you as programmer insist on the use of a keyword? Why do you insist that your property is called 'unit'? It's just obfuscating the code. With this you can mangle your code completely...

Delphi (and Chrome) introduced this escaping mechanism because they had to survive in an environment where they needed to consume and extend types which have been defined in another language with a different set of reserved keywords. It is NOT intended for you to go wild and start naming everything with funny names. The example given was purely my test project to see if it works. Not intended as an example of what you should do.

With FPC supporting different modes and keywords being dependant on mode you are in exactly the same boat as Delphi and Chrome. You might need to access symbols that for you (under the current mode) are a keyword but under the mode where they were declared are just an identifier.

As Delphi _does_ support this mechanism, if you are interested in keeping compatibility to Delphi you'll have to at least allow this mechanism in $mode delphi.

Just to say it again. This is not a mechanism that should be used for anything but compatibility. If you want to enforce the limitation of the use to compatibility only it's possible to introduce additional checks in the parsing stage (as opposed to the tokenizer where this is currently implemented) that prohibits the use of this mechanism in any cases not related to using or extending an already existing type (meaning that e.g. for declaring methods it is only acceptable if the method is used to implement an interface or to override a virtual method that already has this name). That way you could prevent people from abusing this functionality.

Show quoted text 21 lines
And about the 'method' thing... We could also replace the 'property' keyword by 'something'. Hey, we can also replace method by 'something'! Woudn't that be nice. So you get: type TMyObject = class Fs : String; something Foo; something Bar: Integer; class something ClassFoo; class something ClassBar: Integer; something s : read Fs write Fs; end; Hmm... maye it's better to get rid off 'something' completely, then... In short: why do ou want to get rid of the difference between 'procedure' and 'function'? Or do I miss something completely?

Yes, replacing property with the same keyword creates ambiguities that would require multi token lookahead to resolve. Combining function and procedure into the same keyword does not introduce any ambiguity. You might have noticed that both are represented by the same tprocdef. Their code is generated in the same way and they are called in the same way. From a grammar standpoint "function" and "procedure" are really just noise words. The grammar inside these 2 productions is identical except for one requiring and the other prohibiting a specific sub production. The distinction between procedure and function is an artificial one, take the production for function, make the resulttype optional and you have merged the 2 without creating any ambiguity. Property and methods on the other hand have totally different productions, are represented by different defs, are used in different ways. Using the same keyword for that would be lunacy. ;)

I also want to point out that I'm in no way proposing of adding this to any of the existing modes. I've added it to a new mode Chrome. As for "why do you want to get rid of...", for the same reason you do anything that you do in $mode delphi. Because THEY already did it. (Just in case anyone doesn't know what Chrome is and thinks I'm inventing a new language myself here: http://www.chromesville.com/ ).

Cheers,
Thorsten
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (MingW32)

iD8DBQFFtc72tgfmGfGfuPARAtIdAKCGGx7Ag0VuqmdN+49vf5xcmpqfJgCeKoCh MGZG70cVaBaqDRfM8tTyQnw=
=Dwvy
-----END PGP SIGNATURE-----

Reply by email

Marco van de Voort
to Joost van der Sluis: I'm very against this (especially in mode objfpc), and I don't get the my opinion we have…
I'm very against this (especially in mode objfpc), and I don't get the point at all. In my opinion we have to keep the language as clean as possible.

Agree. Also note that this is only part of Delphi, whose compability is still on hold. E.g. D7 reports "illegal character in input &($26)".

IMHO we end up implementing too much syntax for each and every theoretical case (see also the endless discussions about more information hiding modifiers).

Reply by email

Marco van de Voort
to Thorsten Engler: While playing around with the compiler source to familiarize myself I've produced the…
Show quoted text 6 lines
c) new $mode: m_chrome Currently baseed on objfpc with the addition of all 3 new mode switches. In addition to a) and b) m_chrome allows the use of "method" as an alternative to both procedure and function (if the method is a procedure or function can simply be determined by the presence of a defined result type).

I don't see even a theoretical benefit in this.

Reply by email

Пётр Косаревский
to Marco van de Voort

If someone thinks, that there is something in these changes, there is no need to change anything in the compiler.

It may be implemented as some IDE plugin: auto substitution of some keywords and names (using comments to store display-names while naming all keywords as they are and names as "nameXXXXXX").

If the IDE is in graphical mode, pictures may be keywords/names.

If there is an internet connection, webpages (via url) may be used to display keywords or names.

Why change compiler?

Reply by email

Michael Van Canneyt
to Thorsten Engler: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Delphi (and Chrome) introduced this…
Thorsten Engler wrote 7 lines
I also want to point out that I'm in no way proposing of adding this to any of the existing modes. I've added it to a new mode Chrome. As for "why do you want to get rid of...", for the same reason you do anything that you do in $mode delphi. Because THEY already did it. (Just in case anyone doesn't know what Chrome is and thinks I'm inventing a new language myself here: http://www.chromesville.com/ ).

I know what chrome is since the day remobjects started it :-)

But, the 'importing identifiers' from another language is a false argument;
With a simple rule (prepend with _) you have this too. It can even be
automated. You don't need to butcher the language for it;

Why would language A butcher itself in order to accomodate importing language B ? Only commercial people can think of such a thing...

It's like Mercedes saying 'Well, the star symbol on the hood is optional. You can replace it with the token of BMW'. No way that will ever happen.

As for compatibility with Delphi: Yes. Up to a certain degree. If we're going to do this, we'll have to do a lot of other things as well, which have been refused till now...

Michael.

Reply by email

George Birbilis
to Пётр Косаревский: If someone thinks, that there is something in these changes, there is no need to change…
It may be implemented as some IDE plugin: auto substitution of some

keywords and names (using comments to store display-names while naming all keywords

as they are and names as "nameXXXXXX").

With Sun Java and MS J++ or .NET J# I try to use single Java code files and different projects pointing to those same source files. It would be very nice if there was full compatibility with Delphi an with Chrome (I'd then set the switch in the respective project options instead of having to edit or comment it out in each source file everytime I compile using a different environment)

-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-
George Birbilis ()
Microsoft MVP J# 2004-2007
Borland "Spiriti of Delphi"
QuickTime QTVR ActiveX .NET Delphi
http://www.kagi.com/birbilis
http://birbilis.spaces.live.com
-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-

Reply by email

Michael Van Canneyt
to George Birbilis
George Birbilis wrote 11 lines
>It may be implemented as some IDE plugin: auto substitution of some keywords and names (using comments to store display-names while naming all keywords >as they are and names as "nameXXXXXX"). With Sun Java and MS J++ or .NET J# I try to use single Java code files and different projects pointing to those same source files. It would be very nice if there was full compatibility with Delphi an with Chrome (I'd then set the switch in the respective project options instead of having to edit or comment it out in each source file everytime I compile using a different environment)

Well, ask them to support FPC, and code in FPC syntax.

Why would we always have to follow them ? We were first on Linux, on all other platforms, we were the first with native 64 bit support, we were the first to introduce a number of new things. (which they of course implemented differently after that).

That makes a pretty good case for them following us, and not we following them.

Michael.

Reply by email

Пётр Косаревский
to Michael Van Canneyt
> With Sun Java and MS J++ or .NET J# I try to use single Java code files and

I believe the financial leverage makes good Java IDE (IntelliJ IDEA or Eclipse) hard to pursue (in this meaning).

If I get it right, FPC or Lazarus don't have resources to do it.

My point was: instead of trying to patch FPC and Pascal language itself, try to create plugin for an IDE.

Reply by email

Aleš Katona
to Michael Van Canneyt: Well, ask them to support FPC, and code in FPC syntax. Why would we always have to follow…
Michael Van Canneyt wrote 9 lines
Well, ask them to support FPC, and code in FPC syntax. Why would we always have to follow them ? We were first on Linux, on all other platforms, we were the first with native 64 bit support, we were the first to introduce a number of new things. (which they of course implemented differently after that). That makes a pretty good case for them following us, and not we following them.

I agree. I'm starting to feel sick of all the compat crap you guys put up with playing the bitch of delphi. The problem is that now delphi is the bitch of .net so I think wisest would be to implement 100% compat up to delphi 7 and be done with it. Then just document the fact and point people to mode objfpc and our new stuff.

You know I'm open to new things but I think doing compat past D7 is in 99% a waste of time resources and impurification of the language (most .net guys won't go to fpc anyhow, they'll eventually switch to C#)

Michael.

Ales

_______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel
Aleš Katona

Reply by email

Bram Kuijvenhoven
to Michael Van Canneyt: I know what chrome is since the day remobjects started it :-) But, the 'importing…
Michael Van Canneyt wrote
But, the 'importing identifiers' from another language is a false argument; With a simple rule (prepend with _) you have this too. It can even be automated. You don't need to butcher the language for it;

The _ trick is widely used indeed, but imho those underscores make code slightly less readable and also less aesthetic.

Though I understand it's not top class priority to add this to FPC, I like the feature. Not only imports from other languages need adaptation, also names like 'class', 'type' and 'unit' naturally arise as identifier names in certain contexts. I see this for example in a parser I wrote, where I had to rename the very natural 'type' and 'class' to '_type' and '_class' respectively.

A small disadvantage is that code highlighters will need to be adapted, and not all code highlighters might support the requirement that keywords are not to be recognized/highlighted as keywords when they follow a . or & directly.

BTW, I'd welcome the foreach loop, in particular in combination with generics and some standard set of container classes. These are just user wishes of course, you guys are doing a great job already!

Regards,

Bram

Reply by email

Marco van de Voort
to Bram Kuijvenhoven
Show quoted text 7 lines
Michael Van Canneyt wrote: > But, the 'importing identifiers' from another language is a false argument; > With a simple rule (prepend with _) you have this too. It can even be > automated. You don't need to butcher the language for it; The _ trick is widely used indeed, but imho those underscores make code slightly less readable and also less aesthetic.

Less readable than & ? What is the exact aesthetic ranking of ()_+ then? :-)

Reply by email

Michael Van Canneyt
to Bram Kuijvenhoven: The _ trick is widely used indeed, but imho those underscores make code slightly less…
Bram Kuijvenhoven wrote 7 lines
Michael Van Canneyt wrote: > But, the 'importing identifiers' from another language is a false argument; > With a simple rule (prepend with _) you have this too. It can even be > automated. You don't need to butcher the language for it; The _ trick is widely used indeed, but imho those underscores make code slightly less readable and also less aesthetic.

So instead you'd put a & ?

Hardly more readable, I'd say. On the contrary. _ is used already, & is not.

Michael.

Reply by email

Michael Van Canneyt
to Marco van de Voort: Less readable than & ? What is the exact aesthetic ranking of ()_+ then? :-)
Marco van de Voort wrote 10 lines
> Michael Van Canneyt wrote: > > But, the 'importing identifiers' from another language is a false argument; > > With a simple rule (prepend with _) you have this too. It can even be > > automated. You don't need to butcher the language for it; > > The _ trick is widely used indeed, but imho those underscores make code > slightly less readable and also less aesthetic. Less readable than & ? What is the exact aesthetic ranking of ()_+ then? :-)

That's a nice one, Marco :-)

Michael.

Reply by email

Thorsten Engler
to Marco van de Voort: Less readable than & ? What is the exact aesthetic ranking of ()_+ then? :-)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Show quoted text 5 lines
> The _ trick is widely used indeed, but imho those underscores make > code slightly less readable and also less aesthetic. Less readable than & ? What is the exact aesthetic ranking of ()_+ then? :-)

& is an proper escaping mechanism. Renaming the imported symbol with an _ is a hack, and not a pretty one (IMHO, YMMV), as _ is a valid character in identifiers so there might already be a symbol defined with the same name as the one you want to give your renamed imported symbol. What then? You'll have to further rename one of the 2. And that might conflict with something else again and you could end up with a complete chain of renamed symbols. Any renaming involving characters that are valid in identifiers just creates the possibility for more conflicts. And if you are then looking at the documentation or original source of whatever you imported and and what to use it you have to figure out all the time what the new name of the symbols is. On the other hand with a well defined escaping mechanism you use the original symbol names as given, if there is a conflict you use the escape operator. Always exactly the same. And looking at your code all the identifiers match exactly with the source, documentation and examples of whatever you imported.

Cheers,
Thorsten
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (MingW32)

iD8DBQFFtePktgfmGfGfuPARAiNGAJwM45xHByIYb946jPIgx9ij9MtqPQCeIIfu bnXa1TrrudcI64QYOc5RBEU=
=A2Xp
-----END PGP SIGNATURE-----

Reply by email

Felipe Monteiro de Carvalho
to Bogusław Brandys: If libraries are using pure C then you are lucky.If C++ ,then the only reasonable way for…
Bogusław Brandys wrote
If libraries are using pure C then you are lucky.If C++ ,then the only reasonable way for me is a thin wrapper DLL(s) :-(

But imagine if we require a dll to create apps for a operating system. omg, that would look like vb!!! =)

It´s a no-no-no for me.

There are some factors which make this problem less problematic with Symbian OS. The operating system has only 1 binary of one version being distributed. It is not going to be compiled with odd compilers that change name mangling, so the libraries on symbian os have exactly 1 name mangling, which is from one of the recent GCCs. That should be enougth to avoid external dlls.

Felipe Monteiro de Carvalho

Reply by email

Thorsten Engler
to Michael Van Canneyt: So instead you'd put a & ? Hardly more readable, I'd say. On the contrary. _ is used…

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

So instead you'd put a & ? Hardly more readable, I'd say. On the contrary. _ is used already, & is not.

And that's exactly the reason for using & and not _. It's not part of a valid identifier.

If you look at:

&class

You see directly it's the escaped identifier "class". The & doesn't naturally read as part of the identifier.

If you look at:

_class

You read it as the identifier "_class". _ is a valid part of an identifier and people reading source are used to parsing it that way. In addition, starting identifiers with an _ is very common to say "that's private, keep you fingers off". E.g. I see often enough in the compiler source currently that there is a public property and the private variable has the same name prefixed by _. If you are overloading the meaning of identifiers starting with an underscore with both "that's private" and "bummer, we had a keyword conflict". Then you are causing confusion.

Cheers,
Thorsten
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (MingW32)

iD8DBQFFteY9tgfmGfGfuPARAuT2AKCWcqtzDBZqgkgZ0BL0gN6bgRXiwwCeJ09N 1uUfAWgfXS9+eEFR7i3whmQ=
=/nWz
-----END PGP SIGNATURE-----

Reply by email

Michael Van Canneyt
to Thorsten Engler
Thorsten Engler wrote 26 lines
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 > So instead you'd put a & ? > > Hardly more readable, I'd say. On the contrary. _ is used > already, & is not. And that's exactly the reason for using & and not _. It's not part of a valid identifier. If you look at: &class You see directly it's the escaped identifier "class". The & doesn't naturally read as part of the identifier. If you look at: _class You read it as the identifier "_class". _ is a valid part of an identifier and people reading source are used to parsing it that way.

But it is an identifier ?

Show quoted text 5 lines
In addition, starting identifiers with an _ is very common to say "that's private, keep you fingers off". E.g. I see often enough in the compiler source currently that there is a public property and the private variable has the same name prefixed by _.

Not by me :)

If you are overloading the meaning of identifiers starting with an underscore with both "that's private" and "bummer, we had a keyword conflict". Then you are causing confusion.

All the more reason for keeping away from all this and keeping the language clean by clearly separating the identifiers from keywords, and not resorting to additional syntax to be able to use a keyword as an identifer ! :-)

But this is a discussion about principles. Neither expects to convince the other, I think. At least I don't :-)

In each case, it seems a new compiler mode 'Chrome' is born. Well, it's something that was probably bound to happen. One one hand I'm not happy about it (it brings ugly things IMHO) but on the other hand, it's a plus for FPC, being able to compile chrome code...

Michael.

Reply by email

Michael Schnell
to Peter Popov: The simple answer is that you cannot reliably mix object oriented langugages without…

Thanks for the clarifying statement, Peter

I's obvious that linking Object Pascal and C++ in that way is not possible.

OTOH, is interfaces not invented for object based inter-language communication ?

So an interface based DLL layer, converting the C++ API of the OS to interfaces FP could use, might be a more decent way to go that to go back to pure C.

-Michael

Reply by email

Marco van de Voort
to Michael Schnell
Show quoted text 7 lines
Thanks for the clarifying statement, Peter I's obvious that linking Object Pascal and C++ in that way is not possible. OTOH, is interfaces not invented for object based inter-language communication ?

Yes. But between willing partners, not for OOP language A to be able to access any OOP language B without cooperation from B.

People often think this because e.g. on windows there are some similarities between object layout because of COM. But this is an exception, not a rule.

Reply by email

Sebastian Kaliszewski
to Peter Popov: The simple answer is that you cannot reliably mix object oriented langugages without…

To clarify a bit...

Peter Popov wrote
A C++ class CANNOT have a virtual destructor (the VMT is killed when you call delete, before the class' destructor is called).

Nope. Virtual destructors exist in C++, moreover good practice is to make destructor virtual if any other method is virtual. The problem is that there could be non virtual ones as well.

In fact, C++ classes need not have a

rgds
\SK

Reply by email

Bram Kuijvenhoven
to Marco van de Voort: Less readable than & ? What is the exact aesthetic ranking of ()_+ then? :-)
Marco van de Voort wrote 9 lines
> Michael Van Canneyt wrote: >> But, the 'importing identifiers' from another language is a false argument; >> With a simple rule (prepend with _) you have this too. It can even be >> automated. You don't need to butcher the language for it; > The _ trick is widely used indeed, but imho those underscores make code > slightly less readable and also less aesthetic. Less readable than & ? What is the exact aesthetic ranking of ()_+ then? :-)

It is ranked as ..... cartoon! :)

You are right that putting & instead of _ everywhere doesn't seem to make a big difference. On the other hand, in code with lot of .'s, the & doesn't have to be repeated (e.g. MyOject.Class.Property.Type, instead of MyObject._Class._Property._Type).

Personally though, I agree with Thorsten that the & looks prettier than the _. And actually I switched from the _PrivateFieldName convention to the FPrivateFieldName one exactly because the __ messed up.

Well, if for Chrome and/or Delphi support we need the &, then it will have to be implemented anyway. But whether one wants to use it, might simply be a matter of taste.

Regards,

Bram

Reply by email

Dominique Leducq
to Felipe Monteiro de Carvalho: But imagine if we require a dll to create apps for a operating system. omg, that would…
Show quoted text 18 lines
On 1/23/07, Bogusław Brandys wrote: > If libraries are using pure C then you are lucky.If C++ ,then the only > reasonable way for me is a thin wrapper DLL(s) :-( But imagine if we require a dll to create apps for a operating system. omg, that would look like vb!!! =) It´s a no-no-no for me. There are some factors which make this problem less problematic with Symbian OS. The operating system has only 1 binary of one version being distributed. It is not going to be compiled with odd compilers that change name mangling, so the libraries on symbian os have exactly 1 name mangling, which is from one of the recent GCCs. That should be enougth to avoid external dlls. -- Felipe Monteiro de Carvalho

Did anyone have a look at Swig ? (http://www.swig.org) pascal is not supported yet, but it makes much more sense IMHO to add a (object) pascal module to Swig than reinvent the wheel and add some bloat to the compiler.

Basically, Swig automatically generates wrappers for C/C++ code to be used by other programing languages. Initially mainly scripting languages where targeted, but now some compiled languages are supported too. Most of C++ features are supported.
C++ classes are flattened to present a C-like interface, and if the target language supports it, they are wrapped in proxy classes in it. There are plenty of features, and the documentation is extensive and well written, with lot of examples.

Dominique Leducq

Reply by email

Daniël Mantione
to Bram Kuijvenhoven: It is ranked as ..... cartoon! :) You are right that putting & instead of _ everywhere…

Op Tue, 23 Jan 2007, schreef Bram Kuijvenhoven:

Well, if for Chrome and/or Delphi support we need the &, then it will have to be implemented anyway.

Only if we are able to compile code we currently cannot compile. For Chrome it would be a long term project before you can compile anything, since any Chrome code uses .NET libraries. Further, FPC code won't import types or extent objects from other .NET languages, as it is not a .NET compiler. There is nothing bad about being Chrome compatible, but one has to argue how realistic it is.

For Delphi, most Delphi code bases are Win32 and don't use .NET language features. If that changes, the urgence for FPC to have D8+ features increases. Until now, D7 as limit has been a good choice.

But whether one wants to use it, might simply be a matter of taste.

There are many disgusting language features in Delphi. There are several ways of dealing with those:
1) Support them fully in all modes.
2) Support them only in Delphi mode.
3) Support them in Delphi mode, but remove the fun by printing hints or even warnings.
4) Not supporting them.

The decision depends on a case by case basis. Code exchange between Delphi and Objfpc modes should for example be possible without rewriting the code. So even while a feature is a bit ugly, it can get into category 1. However, a feature that is just a type saver could go into category 2, and if it endangers type-safety or code correctness, it can go into category 3.

As some Delphi 8+ features break all ugliness records, expect them to be put into categories 2,3,4.

Daniël

Reply by email

Luiz Americo Pereira Camara
to Aleš Katona: I agree. I'm starting to feel sick of all the compat crap you guys put up with playing…
Aleš Katona wrote 6 lines
I agree. I'm starting to feel sick of all the compat crap you guys put up with playing the bitch of delphi. The problem is that now delphi is the bitch of .net so I think wisest would be to implement 100% compat up to delphi 7 and be done with it. Then just document the fact and point people to mode objfpc and our new stuff.

This makes me remenber of copying weird behaviors of Delphi. As an example see the code:

 AList:=TStringList.Create;
  with AList do
  begin
    writeln('Set a string with space (aaaa;bb bb;cccc) to DelimitedText');
    DelimitedText:='aaaa;bb bb;cccc';
    writeln('Count: ',Count);
    writeln('Delimited text: ',DelimitedText);
    writeln('Strings: ');
    for i:= 0 to Count - 1 do
      writeln('  ',Strings[i]);
    Destroy;
  end;

Output:
Set a string with space (aaaa;bb bb;cccc) to DelimitedText Count: 4
Delimited text: aaaa;bb;bb;cccc
Strings:
aaaa
bb
bb
cccc

The space is used as a hardcoded delimiter being necessary to enclose with ". This limits the use of DelimitedText as a generic approach since is necessary to preprocess the strings being added though DelimitedText.

The argument to keep such behavior is compatibility but there will be always differences when porting code and the programmer must be aware. What is necessary is to document the differences. So in resume i think that fpc must not follow strictly Delphi, and in some situations, where appropriated, fpc can/must do things different/better than Delphi.

Luiz

Reply by email

Daniël Mantione
to Luiz Americo Pereira Camara

Op Tue, 23 Jan 2007, schreef Luiz Americo Pereira Camara:

Show quoted text 44 lines
Ale? Katona wrote: > I agree. I'm starting to feel sick of all the compat crap you guys put > up with playing the bitch of delphi. The problem is that now delphi is > the bitch of .net so I think wisest would be to implement 100% compat up > to delphi 7 and be done with it. Then just document the fact and point > people to mode objfpc and our new stuff. > This makes me remenber of copying weird behaviors of Delphi. As an example see the code: AList:=TStringList.Create; with AList do begin writeln('Set a string with space (aaaa;bb bb;cccc) to DelimitedText'); DelimitedText:='aaaa;bb bb;cccc'; writeln('Count: ',Count); writeln('Delimited text: ',DelimitedText); writeln('Strings: '); for i:= 0 to Count - 1 do writeln(' ',Strings[i]); Destroy; end; Output: Set a string with space (aaaa;bb bb;cccc) to DelimitedText Count: 4 Delimited text: aaaa;bb;bb;cccc Strings: aaaa bb bb cccc The space is used as a hardcoded delimiter being necessary to enclose with ". This limits the use of DelimitedText as a generic approach since is necessary to preprocess the strings being added though DelimitedText. The argument to keep such behavior is compatibility but there will be always differences when porting code and the programmer must be aware. What is necessary is to document the differences. So in resume i think that fpc must not follow strictly Delphi, and in some situations, where appropriated, fpc can/must do things different/better than Delphi.

Yes, but unless it is clearly a Delphi bug, it is better to keep the Delphi compatible procedure or class and write a new clean one. Wether something is a bug or intended behaviour usually becomes clear after reading the the documentation.

Daniël

Reply by email

Peter Popov
to Michael Schnell: Thanks for the clarifying statement, Peter I's obvious that linking Object Pascal and C++…

Yes, this is the original purpose of interfaces in Delphi 3 and later: reuse object code from different languages/executables through COM/DCOM or CORBA. Both define standards for RPC (Remote procedure calling) and passing arguments (type and size). An interface only exports member functions (any data members will create incompatibility problems: what is the data layout of the class, etc). Construction is by factory function, destruction is by reference counting (so it is done on the server side and the client does not have to do any memory management).

The implementation of CORBA is actually quite involved: the object hieararchy to be reused is described in a separate language (IDL - Interface Definition Language). Then, a CORBA compiler creates a thin layer of stub objects specific to the target programming language. The target programming language can then compile this thin layer, link at compile time, make a DLL and link at run time, etc. So, the server and client sides are independent and only share the object hierarchy description (in IDL). The client language always works with the stub object (compiled in the same langage). The stub transfers the arguments to the CORBA executable, whih passes them to the stub on the servers side. The server serves the result to the CORBE layer, the CORBA passes is to the client stub. So, the results is now visible to the client.

As far as I remember, Delphi 5 and on has an IDL compiler included, and can generate IDL code from an Object Pascal hierarchy. So in FPC one can envision automatic generation of IDL description based on an interface hierarchy. There might, however, already be some parsers (independent of Borland) that do that.

A final remark. Code sharing through COM/DCOM can lead to the following "Hello World" program:
http://www.ffzg.hr/infosl/fun/HelloWorld.htm (see the master programmer example)

Peter

Michael Schnell wrote 17 lines
Thanks for the clarifying statement, Peter I's obvious that linking Object Pascal and C++ in that way is not possible. OTOH, is interfaces not invented for object based inter-language communication ? So an interface based DLL layer, converting the C++ API of the OS to interfaces FP could use, might be a more decent way to go that to go back to pure C. -Michael _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Luiz Americo Pereira Camara
to Daniël Mantione: Op Tue, 23 Jan 2007, schreef Luiz Americo Pereira Camara: Yes, but unless it is clearly a…
Daniël Mantione wrote 55 lines
Op Tue, 23 Jan 2007, schreef Luiz Americo Pereira Camara: > Ale? Katona wrote: > >> I agree. I'm starting to feel sick of all the compat crap you guys put >> up with playing the bitch of delphi. The problem is that now delphi is >> the bitch of .net so I think wisest would be to implement 100% compat up >> to delphi 7 and be done with it. Then just document the fact and point >> people to mode objfpc and our new stuff. >> >> > This makes me remenber of copying weird behaviors of Delphi. As an example see > the code: > > AList:=TStringList.Create; > with AList do > begin > writeln('Set a string with space (aaaa;bb bb;cccc) to DelimitedText'); > DelimitedText:='aaaa;bb bb;cccc'; > writeln('Count: ',Count); > writeln('Delimited text: ',DelimitedText); > writeln('Strings: '); > for i:= 0 to Count - 1 do > writeln(' ',Strings[i]); > Destroy; > end; > > Output: > Set a string with space (aaaa;bb bb;cccc) to DelimitedText > Count: 4 > Delimited text: aaaa;bb;bb;cccc > Strings: > aaaa > bb > bb > cccc > > > The space is used as a hardcoded delimiter being necessary to enclose with ". > This limits the use of DelimitedText as a generic approach since is necessary > to preprocess the strings being added though DelimitedText. > > The argument to keep such behavior is compatibility but there will be always > differences when porting code and the programmer must be aware. What is > necessary is to document the differences. So in resume i think that fpc must > not follow strictly Delphi, and in some situations, where appropriated, fpc > can/must do things different/better than Delphi. > Yes, but unless it is clearly a Delphi bug, it is better to keep the Delphi compatible procedure or class and write a new clean one. Wether something is a bug or intended behaviour usually becomes clear after reading the the documentation.

Ok. Apart from the Delimiter issue, i've heard some complaints about the design of TStringList that would not be scalable etc (a quote of a email sent to fpc-devel below). Maybe is time to add to fpc a new class to store strings, fixing the design flaws? Anyone already has such a base?

Luiz

Show quoted text 20 lines
Michael Van Canneyt wrote: > > > The purpose of Customsearch is to sort the list once using a custom > > > sorting algorithm. > > > That reduces its usefulness, and why I said it's a broken design :) . Well, it fits with the rest of TStringList then :-) Seriously, I wouldn't bother using TStringList. It's position in the VCL and Delphi compat and its fundamental flaws make it too difficult to enhance/improve. (hinting on the scaling problems, the delimited functions always using space as a separator etc) Marco van de Voort

Reply by email

Michael Van Canneyt
to Luiz Americo Pereira Camara
Luiz Americo Pereira Camara wrote 66 lines
Daniël Mantione wrote: > Op Tue, 23 Jan 2007, schreef Luiz Americo Pereira Camara: > > > > Ale? Katona wrote: > > > > > I agree. I'm starting to feel sick of all the compat crap you guys put > > > up with playing the bitch of delphi. The problem is that now delphi is > > > the bitch of .net so I think wisest would be to implement 100% compat up > > > to delphi 7 and be done with it. Then just document the fact and point > > > people to mode objfpc and our new stuff. > > > > > > > > This makes me remenber of copying weird behaviors of Delphi. As an example > > see > > the code: > > > > AList:=TStringList.Create; > > with AList do > > begin > > writeln('Set a string with space (aaaa;bb bb;cccc) to DelimitedText'); > > DelimitedText:='aaaa;bb bb;cccc'; > > writeln('Count: ',Count); > > writeln('Delimited text: ',DelimitedText); > > writeln('Strings: '); > > for i:= 0 to Count - 1 do > > writeln(' ',Strings[i]); > > Destroy; > > end; > > > > Output: > > Set a string with space (aaaa;bb bb;cccc) to DelimitedText > > Count: 4 > > Delimited text: aaaa;bb;bb;cccc > > Strings: > > aaaa > > bb > > bb > > cccc > > > > > > The space is used as a hardcoded delimiter being necessary to enclose with > > ". > > This limits the use of DelimitedText as a generic approach since is > > necessary > > to preprocess the strings being added though DelimitedText. > > > > The argument to keep such behavior is compatibility but there will be > > always > > differences when porting code and the programmer must be aware. What is > > necessary is to document the differences. So in resume i think that fpc > > must > > not follow strictly Delphi, and in some situations, where appropriated, > > fpc > > can/must do things different/better than Delphi. > > > > Yes, but unless it is clearly a Delphi bug, it is better to keep the Delphi > compatible procedure or class and write a new clean one. Wether something is > a bug or intended behaviour usually becomes clear after reading the the > documentation. > Ok. Apart from the Delimiter issue, i've heard some complaints about the design of TStringList that would not be scalable etc (a quote of a email sent to fpc-devel below). Maybe is time to add to fpc a new class to store strings, fixing the design flaws? Anyone already has such a base?

Not really.

I don't believe there is an optimal design. It depends on what you want to use the StringList for. For generic use in the VCL (memo, combobox, listbox, params), TStrings is well suited. Some of the choices Borland made when implementing auxiliary methods are unfortunate, but they can be replaced with better methods, if needed, or new methods can be added. I'm always open for suggestions. But compatibility should be maintained.

For handling large amounts of strings or stringlists for special purposes, it's usually better to write a specialized class. FPC meanwhile contains enough container classes to make this possible.

Michael.

Reply by email

Felipe Monteiro de Carvalho
to Daniël Mantione: Op Mon, 22 Jan 2007, schreef Felipe Monteiro de Carvalho: Already looked at many times,…
Daniël Mantione wrote 5 lines
Op Mon, 22 Jan 2007, schreef Felipe Monteiro de Carvalho: > Maybe the compiler could hide the > procedurization/re-object-orientation, thus making interfacing easier. Already looked at many times, but it is not realistic.

Can you point me to previous discussion of this? Or perhaps a short explanation of why, would be nice =)

I did a quick search on fpc mailling lists, found lot´s of talk about linking to c++ in general, but nothing on the specific topic of hiding the procedurization/re-object-orientation

thanks,

Felipe Monteiro de Carvalho

Reply by email

Christian Iversen
to Felipe Monteiro de Carvalho: I was studing how to write the system unit for Symbian OS, and everything on Symbian is…
Felipe Monteiro de Carvalho wrote 9 lines
Hello, I was studing how to write the system unit for Symbian OS, and everything on Symbian is C++, so you actually import lot´s of methods from classes, not procedures. So I decided to study the task of linking from Free Pascal to C++ Maybe it´s easy to be implemented, and that would be very nice. Here is my test:

I "solved" this problem some time ago. I've put together a small demonstration of how to link a complete C++ class to a pascal program, _without_ using a C-style wrapper (because /that/, anybody can do!)

I've attached two small zipfiles to this mail, which gives two such examples. One is for linking to existing programs, and the other is for creating interfaces suitable for using across several languages with minimal trouble. The interface example needs a little more work, but shows the basic principle.

I hope it's useful.

Regards, Christian Iversen

Reply by email

Peter Popov
to Felipe Monteiro de Carvalho: Can you point me to previous discussion of this? Or perhaps a short explanation of why,…
Show quoted text 14 lines
> Op Mon, 22 Jan 2007, schreef Felipe Monteiro de Carvalho: > > Maybe the compiler could hide the > > procedurization/re-object-orientation, thus making interfacing easier. > > Already looked at many times, but it is not realistic. Can you point me to previous discussion of this? Or perhaps a short explanation of why, would be nice =) I did a quick search on fpc mailling lists, found lot´s of talk about linking to c++ in general, but nothing on the specific topic of hiding the procedurization/re-object-orientation thanks,

For a realistic example, download the Kylix patch for QT3 (http://sourceforge.net/project/showfiles.php?group_id=106820) and look at QtLibrary.pas and QtWrappers.pas

It looks something like this:

/* On the C++ side */

class CMyClass{
.....
public:

     CMyClass(){/* def constructor */};
     ~CMyClass(){/* def destructor */};
     virtual int DoSomething(){ return 42; };

}

/* THE FOLLOWING FUNCTIONS ARE ALL EXPORTED. */
/* The export modifier is different from compiler to compiler, so I skip here */

CMyClass *MyClassFactory(){

   return new CMyClass();

}

DestroyMyClass(CMyClass *instance){

   delete instance();

}

int CMyClass_DoSomething(CMyClass *instance){

   return instance->DoSomething();

}

{ ON THE PASCAL SIDE }

TMyClassImport = class
   protected
     // Override NewInstance and throw a readable exception,
     // explaining that you cannot allocate an imported class.
     // This will happen if you call the Create constructor.
     class function NewInstance: TObject; override;
   public
     // Instead of Create, use the next function as a constructor.
     class function New: TMyClass;
     // This will be used as a destructor
     procedure Delete; cdecl;
     function DoSomething(): Integer; cdecl;
     // Override Free and redirect it to use the Delete function
     // instead of the default Destroy constructor.
     procedure Free; override;
end;
class function TMyClassImport.NewInstance: TObject;
begin
   raise Exception.Create('Please, create an instance by using
TMyClassImport.New');
end;
function MyClassFactory: TMyClassImport; external DLL_NAME
'MyClassFactory';
class function TMyClassImport.New: TMyClassImport;
begin
   Result := MyClassFactory;
end;
TMyClassImport.Delete; cdecl; external DLL_NAME 'DestroyMyClass';
// Override Free and redirect it to use the Delete function
// instead of the default Destroy destructor
TMyClassImport.Free;
begin
   if Self  nil then Delete;
end;
TMyClassImport.DoSomething; cdecl; external DLL_NAME
'CMyClass_DoSomething';

At this point you have all the functionality of CMyClass. Finally, you can define

TMyClass = class
   private
     handle: TMyClassImport;
   public
     function DoSomething: Integer; virtual;
  .......
end;

and here you can redirect all functions to the handle object (TMyClassImport). You can have a normal Create constructor and Destroy destructor, etc. Also, you can do some basic extension of the functionality. In this example,

function TMyClass.DoSomething;
begin
   Result := handle.DoSomething;
end;

Conceivably, you can do some limited extension of DoSomething. TMyClass and all derived classes will allocate a handle of type TMyClassImport so, internally they redirect the calls to the basic methods of CMyClass. So, the C++ side always gets the handle object which has the correct class layout (because it was allocated on the C++ side).

However, suppose that a non-virtual function of CMyClass, say DoSomethingElse, relies on the answer of DoSomething. Any change you make in DoSomething, by dering classes from TMyClass and overriding it will not result in polymorphic behavior of DoSomethingElse. That is, TMyDerivedClass.DoSomethingElse will still forward the handle of the original C++ class (handle.DoSomethingElse) and the later will use the original CMyClass:DoSomething. So the answer will always be 42.

Peter

Reply by email

Michael Schnell
to Peter Popov: Yes, this is the original purpose of interfaces in Delphi 3 and later: reuse object code…
As far as I remember, Delphi 5 and on has an IDL compiler included,

I suppose same is used to generate an interface unit when you do "import type library". Is this possible with TP, too ?

and can generate IDL code from an Object Pascal hierarchy.

I suppose this is true and necessary when creating a COM server. I never tried to do something like this yet.

Show quoted text 9 lines
So in FPC one can envision automatic generation of IDL description based on an interface hierarchy. There might, however, already be some parsers (independent of Borland) that do that. A final remark. Code sharing through COM/DCOM can lead to the following "Hello World" program: http://www.ffzg.hr/infosl/fun/HelloWorld.htm (see the master programmer example)

:-) :-) :-)

-Michael

Reply by email