On Thursday 26 January 2006 20:14, Florian Klaempfl wrote:
> Christian Iversen wrote:
> > On Thursday 26 January 2006 12:55, Felipe Monteiro de Carvalho wrote:
> >>Hello,
> >>
> >>Attached is a patch that changes the current Qt interface into a Qt4
> >>interface.
> >>
> >>The following widgets work: TApplication, TCustomForm, TCustomButton,
> >>TCustomMemo
> >>
> >>It uses Jen Dean qt4 wrapper, which is basically a 800kb .so file that
> >>needs to be on the library path for lcl-qt4 programs to work.
> >
> > I'll bet the farm that the 800kb file is not needed!
> >
> > All you need to do is change the header file slightly. I ported the
> > modplug (module player) header code to linux. Now, modplug is C++, so of
> > course this was a bit of a challenge. However, I managed to use the
> > following style:
> >
> > Procedure SoundFile_FreeSample(p: Pointer); CDecl; External {$IFDEF
> > DYNLINK}libmodplugname{$ENDIF} Name '_ZN10CSoundFile10FreeSampleEPv';
> >
> > Function SoundFile_ReadS3M (Obj : Pointer; lpStream : Pointer;
> > dwMemLength: dword): Bool; CDecl; External {$IFDEF
> > DYNLINK}libmodplugname{$ENDIF} Name '_ZN10CSoundFile7ReadS3MEPKhm';
> >
> > and so on.
>
> How do you handle e.g. virtual calls :) ?
I've been quite busy with my final exams, but I managed to find a little time
to make sample of this.
It's attached here. To run it, do this:
$ gcc -c test.cpp (creates test.o)
$ fpc -Mdelphi virtest.pas && ./virtest
It should print out something like the following:
Free Pascal Compiler version 2.1.1 [2005/12/15] for i386
Copyright (c) 1993-2005 by Florian Klaempfl
Target OS: Linux for i386
Compiling virtest.pas
Linking virtest
94 Lines compiled, 0.3 sec
I got the number 42 as an argument
Reading back a variable: 42
Got 3
I got the number 17 as an argument
Reading back a variable: 17
Please notice that all code except for "Reading back a variable" is entirely
in C++!
Also, the memory maps in the header file is currently made in such a way as to
save typing for me. If it were auto-generated, it would be HUGELY simpler to
access a low-level property of a high-level object (i.e no
object.vmt.parent.parent.parent.parent... )
This is _only_ a proof-of-concept, but it goes to show that it's quite doable
to link in C++ code. Please once again keep in mind that the access method
will look much nicer in a possible real version.
--
Regards,
Christian Iversen
#include <stdio.h>
class foo {
private:
public:
int foo;
virtual void frob(int x) {
foo = x;
}
virtual void nicate() {
printf("I got the number %d as an argument\n", foo);
}
};
class bar : public foo {
virtual void frobnicate(int x) {
printf("Got %d\n", x);
}
};
foo* new_foo() {
return new foo();
}
bar* new_bar() {
return new bar();
}
program test;
{$LINK 'test.o'}
{$LINKLIB 'c'}
uses
LibC, sysutils;
type
tfrobber = procedure(obj: pointer; x: integer); stdcall;
tnicater = procedure(obj: pointer); stdcall;
// VMTs for Foo and Bar
tfoovmt =
record
frob: procedure(obj: pointer; x: integer); stdcall;
nicate: procedure(obj: pointer); stdcall;
end;
pfoovmt = ^tfoovmt;
tbarvmt =
record
parent: tfoovmt;
frobnicate: procedure(obj: pointer; x: integer); stdcall;
end;
pbarvmt = ^tbarvmt;
// Memory maps for Foo and Bar
tfoovars =
record
x: integer;
end;
tbarvars =
record
parent: tfoovars;
end;
// Class maps for Foo and Bar
tfooclass =
record
vmt: pfoovmt;
vars: tfoovars;
end;
pfooclass = ^tfooclass;
tbarclass =
record
vmt: pbarvmt;
vars: tbarvars;
end;
pbarclass = ^tbarclass;
// Custom constructors
function new_foo(): pfooclass; external name '_Z7new_foov';
function new_bar(): pbarclass external name '_Z7new_barv';
function new_integer(x: integer): pointer;
begin
result := malloc(x);
end;
procedure dummy();
begin
end;
// Quiesce the linker - g++ needs this to be defined
exports
dummy name '__gxx_personality_v0',
dummy name '_ZTVN10__cxxabiv117__class_type_infoE',
dummy name '_ZTVN10__cxxabiv120__si_class_type_infoE',
new_integer name '_Znwj';
var
x: pfooclass;
y: pbarclass;
begin
x := new_foo();
y := new_bar();
x.vmt.frob(x, 42);
x.vmt.nicate(x);
writeln('Reading back a variable: ', x.vars.x);
y.vmt.frobnicate(y, 3);
y.vmt.parent.frob(y, 17);
y.vmt.parent.nicate(y);
writeln('Reading back a variable: ', y.vars.parent.x);
end.