[fpc-devel] Interfaces (long post)
Leonardo M. Ram�
martinrame at yahoo.com
Sun Jun 4 00:14:15 CEST 2006
I'm trying to port a program i wrote in Delphi to
FPC & Kylix and found when an interfaced
object (COM interface, not CORBA) is instantiated
and call the _AddRef method, in Kylix is executed
one time (as expected) but in FPC is called
two times losing the refcount.
The correct result is this (compiled in Kylix):
--------------------
Loaded!
TMyIntfClass._AddRef
--------------------
The program compiled in FPC produces this:
--------------------
Loaded!
TMyIntfClass._AddRef
TMyIntfClass._AddRef
--------------------
By the way...
If you compile test.dpr using FPC and the library
with Kylix (or the contrary), instead of _AddRef,
you'll receive an AV. Anybody knows why?.
Thank's for reading this long post.
Sincerely,
Leonardo M. Ramé
Córdoba, Argentina
This is the code (I used FPC 2.0.2 & Kylix 3):
-------------------------------------------------
{ interfaces.dpr }
library interfaces;
uses
Classes,
intf_classes;
function KNL_GetClass(AClassName: PChar): Integer; cdecl;
(* I get pointers to classes as Integers (nice hack!) *)
begin
Result := Integer(GetClass(AClassName));
end;
exports
KNL_GetClass;
end.
--------------------------------------------------
{ intf_classes.pas }
unit intf_classes;
interface
uses
Classes;
type
IMyInterface = interface
['{C6785134-AF18-4FB3-8DB1-080DE6D152FC}']
end;
TMyIntfClass = class(TInterfacedPersistent, IMyInterface)
private
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
end;
implementation
function TMyIntfClass._AddRef: Integer;
begin
writeln('TMyIntfClass._AddRef');
Result := -1;
end;
function TMyIntfClass._Release: Integer;
begin
Result := -1;
end;
initialization
(* Registramos las classes *)
RegisterClass(TMyIntfClass);
finalization
(* Quitamos las registrciones *)
UnregisterClass(TMyIntfClass);
end.
--------------------------------------------------
{ test.dpr }
program test;
uses
{$ifdef fpc}
dynlibs,
{$endif}
SysUtils,
Classes;
type
IMyInterface = interface
['{C6785134-AF18-4FB3-8DB1-080DE6D152FC}']
end;
TMyImplementation = class(TInterfacedPersistent, IMyInterface)
private
FInternalObj: IMyInterface;
public
constructor Create;
end;
var
{$ifdef fpc}
mHandle: TLibHandle;
{$else}
mHandle: THandle;
{$endif}
function KNL_GetClass(AClass: string): TPersistentClass;
(* wrapper to GetClass from shared library. *)
var
_GC: function (AClass: PChar): Integer; cdecl;
begin
_GC := GetProcAddress(mHandle, 'KNL_GetClass');
if (Integer(@_GC) <> 0) then
Result := TPersistentClass(_GC(PChar(AClass)));
end;
constructor TMyImplementation.Create;
begin
(* Here aparently calls two times _AddRef of TMyIntfClass *)
FInternalObj :=
TMyImplementation(KNL_GetClass('TMyIntfClass').Create) as IMyInterface;
end;
var
myObj: TMyImplementation;
begin
(* load shared library *)
if (pointer(mHandle) = nil) then
begin
(* Try to load shared library
(in win32 use interfaces.dll instead of libinterfaces.so) *)
mHandle := LoadLibrary('./libinterfaces.so');
if (pointer(mHandle) <> nil) then
begin
writeln('Loaded!');
(* instantiate a TMyImplementation object *)
myObj := TMyImplementation.Create;
(* Free instances *)
myObj.Free;
(* unload shared library *)
{$ifdef fpc}
UnLoadLibrary(mHandle);
{$else}
FreeLibrary(mHandle);
{$endif}
end;
end;
end.
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
More information about the fpc-devel
mailing list