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 VMT at all. If 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

On Mon, 22 Jan 2007 13:17:48 -0600, Felipe Monteiro de Carvalho <[EMAIL PROTECTED]> wrote:

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,

|***********************************************|
_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply via email to