Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C++, Delphi] Vertaling van header file van C++ naar Delphi

Pagina: 1
Acties:

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 24-11 12:27

Tomatoman

Fulltime prutser

Topicstarter
In een header file van de AMD Core Math Library (AMCL) kom ik de volgende regel tegen:
C:
1
extern void scfft(int mode, int n, float *x, float *comm, int *info);
In mijn header translation naar Delphi maak ik dit ervan:
Delphi:
1
2
procedure scfft(mode, n: Integer; var x, comm: Single; 
  out info: Integer); stdcall;

De user guide (gebaseerd op FORTRAN) zegt er het volgende over:
SCFFT(MODE,N,X,COMM,INFO)

[Input] INTEGER MODE
The value of MODE on input determines the operation performed by SCFFT.
On input:
• MODE=0 : only initializations (specific to the value of N) are performed;
this is usually followed by calls to the same routine with MODE= 1.
• MODE=1 : a real transform is performed. Initializations are assumed to
have been performed by a prior call to SCFFT.
• MODE=2 : initializations and a real transform are performed.

[Input] INTEGER N
On input: N is the length of the real sequence X

[Input/Output] REAL X(N)
On input: X contains the real sequence of length N to be transformed.
On output: X contains the transformed Hermitian sequence.

[Input/Output] REAL COMM(2*N+100)
COMM is a communication array. Some portions of the array are used to
store initializations for subsequent calls with the same sequence length N. The
remainder is used as temporary store.

[Output] INTEGER INFO
On output: INFO is an error indicator. On successful exit, INFO contains 0.
If INFO = -i on exit, the i-th argument had an illegal value.

Example:
Fortran:
1
2
3
4
5
6
7
    CALL SCFFT(0,N,X,COMM,INFO)
    CALL SCFFT(1,N,X,COMM,INFO)
    CALL SCFFT(1,N,Y,COMM,INFO)
    DO 10 I = 1, N
      X(I) = X(I)*Y(N-I+1)
10  CONTINUE
    CALLD CSFFT(1,N,X,COMM,INFO)
x en comm zijn dus placeholders voor een array.

Als ik de functie in Delphi aanroep met mode = 0, retourneert hij weliswaar de waarde nul in info, maar wordt ergens een geheugenblok klaarblijkelijk gecorrumpeerd. Gevolg: een crash op een onvoorspelbaar moment. Een aansluitende aanroep van scfft met mode = 1 geeft voor info de waarde 1 of 2; ik heb geen idee wat die foutcodes betekenen.

Heeft iemand een idee wat ik verkeerd doe? Klopt de header translation wel?

Een goede grap mag vrienden kosten.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 03:45
Klopt de calling convention wel? Ik zou denken dat een C-functie een ccall calling convention heeft maar je declareert je functie met stdcall calling convention. Aan de andere kant hebben ccall en stdcall verschillende name mangling regels dus dan zou je verwachten dat je al bij het linken foutmeldingen krijgt.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 24-11 12:27

Tomatoman

Fulltime prutser

Topicstarter
In Delphi wordt de stdcall directive gebruikt om de C calling convention te gebruiken. Met andere functies in dezelfde header translation werkt dat probleeemloos, dus dat lijkt het probleem niet te zijn.

Jouw opmerking zou me niettemin echter weleens in de goede richting kunnen brengen, want met de cdecl calling convention kom ik al heel wat regels verder voordat het programma crasht.

Een goede grap mag vrienden kosten.


  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 25-11 15:13
x en comm zijn arrays

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 24-11 12:27

Tomatoman

Fulltime prutser

Topicstarter
In Delphi is er helaas geen manier om dat duidelijk te maken in de functiedeclaratie. In de praktijk werkt het prima door simpelweg het eerste element van een array als parameter aan de functie mee te geven.

Het blijkt inderdaad dat de calling convention verkeerd was. Met cdecl in plaats van stdcall is dat probleem opgelost. Om het nog wat moeilijker te maken blijkt de documentatie een fout te bevatten 8)7[norml]:[/]
[Input/Output] REAL COMM(2*N+100)
Dit moet zijn:
[Input/Output] REAL COMM(3*N+100)
Bedankt AMD :(. (Ik wist deze fout op te sporen aan de hand van een paar voorbeeldprogramma's in C.)

Nu al deze hordes zijn genomen, is er nog een ander probleem. De ACML library vindt het niet leuk om in en uit het geheugen geladen te worden (LoadLibrary/FreeLibrary). Gevolg: mijn applicatie hangt. Ik heb nog geen idee wat ik hieraan moet doen :|.
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
var
  Lib: Cardinal;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Lib := LoadLibrary('libacml.dll');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  FreeLibrary(Lib);
end;
De event handler Button1Click is al genoeg om mijn applicatie te laten hangen.

Een goede grap mag vrienden kosten.


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 22:53

Creepy

Tactical Espionage Splatterer

Zijn er nog speciale dingen die je doet in de initialization of finalization in units van je DLL?

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 24-11 12:27

Tomatoman

Fulltime prutser

Topicstarter
De dll is gemaakt door AMD en de source code is niet vrijgegeven. Ik roep de dll zelf aan vanuit mijn applicatie. Of ik de dll statisch of dynamisch laad, maakt geen verschil: het programma sluit af met een access violation (buiten Delphi) of sluit überhaupt niet af (binnen Delphi). De dll kent geen DllRegisterServer of iets dergelijks (heb ik al getest).

Een goede grap mag vrienden kosten.


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 22:53

Creepy

Tactical Espionage Splatterer

tomatoman schreef op 07 april 2004 @ 15:07:
De dll is gemaakt door AMD en de source code is niet vrijgegeven. Ik roep de dll zelf aan vanuit mijn applicatie. Of ik de dll statisch of dynamisch laad, maakt geen verschil: het programma sluit af met een access violation (buiten Delphi) of sluit überhaupt niet af (binnen Delphi). De dll kent geen DllRegisterServer of iets dergelijks (heb ik al getest).
Ah, my mistake.

Kan je de functies als "extern" declareren en zo gebruiken i.p.v. loadlibrary, of moet je perse @runtime de DLL laden?

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 24-11 12:27

Tomatoman

Fulltime prutser

Topicstarter
Het kan allebei en het levert hetzelfde resultaat op. Ik hoef niet eens een functie in de dll aan te roepen, simpelweg het laden ervan veroorzaakt al het probleem.

Een goede grap mag vrienden kosten.


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 22:53

Creepy

Tactical Espionage Splatterer

Eeeehh... weet je zeker dat het een normale windows DLL is? In de voorbeelden/documentatie zie ik ze dynamisch linken met g77/gcc tegen de DLL aan. Er staat ook specifiek bij dat het voor gebruik met g77/gcc i.c.m. cygwin is.

Want als de boel al meteen crasht bij een LoadLibrary lijkt me iets niet in orde met de DLL.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 24-11 12:27

Tomatoman

Fulltime prutser

Topicstarter
De boel crasht pas bij het afsluiten van mijn programma (eigenlijk ieder Delphi-programma dat de dll laadt), waaruit ik opmaak dat het unloaden van libacml.dll het probleem veroorzaakt.

Ik zal de functie eens herschrijven, zodat de dll dynamisch wordt geladen. In de voorbeelden in C die ik zie, wordt de dll trouwens altijd statisch gelinkt.

Een goede grap mag vrienden kosten.


  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 25-11 15:13
tomatoman schreef op 07 april 2004 @ 04:22:
[...]
In Delphi is er helaas geen manier om dat duidelijk te maken in de functiedeclaratie. In de praktijk werkt het prima door simpelweg het eerste element van een array als parameter aan de functie mee te geven.
Delphi:
1
2
3
4
5
type
  float = single;

  PFloatArray = ^TFloatArray;
  TFloatArray = array[0..MaxInt div SizeOf(float)-1] of float;


Dan kan je het type PFloatArray gebruiken voor de x en comm argumenten
Pagina: 1