[fpc-devel] Linking to C++

Peter Popov ppopov at tamu.edu
Tue Jan 23 23:27:20 CET 2007


>> 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





More information about the fpc-devel mailing list