Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi habe DLL aber nur C++ und VB Beispiele (https://www.delphipraxis.net/37843-habe-dll-aber-nur-c-und-vbulletin-beispiele.html)

alf.stefan 11. Jan 2005 10:04


habe DLL aber nur C++ und VB Beispiele
 
Hallo zusammen

ich habe eine DLL die ich verwenden will. Der Hersteller der das vertreibt unterstützt aber nur VB und C++.
Also sind in seiner Dokumentation auch nur VB und C++ Beispiele dabei.
Ich will aber Delphi verwenden also hab ich mal angefangen die C++ Header Files bzw. die entprechende .Bas Datei in Delphi zu übersetzen.
Das geht so weit auch. Und einige wenige funktionen kann ich auch schon beutzen
(vor allem die ohne Parameter Übeergabe)

C++

KMErrorCode EXPORTFCN KMTCPRefreshDevices( void ); // funktioniert in delphi
KMErrorCode EXPORTFCN KMTCPGetNumDevices( LPUINT16 lpnNumDevices ); // das auch

delphi
Function KMTCPRefreshDevices (): Long; cdecl; external 'KmApi32.DLL';
Function KMTCPGetNumDevices (lpnNumDevices : pWord): Long; cdecl; external 'KmApi32.DLL';

aber bei folgender Funktion geht nix
C++
/* TCPIP Server Control access functions */
KMErrorCode EXPORTFCN KMTCPGetDeviceInformation(char *lpszNameArray[], char *lpszAddressArray[], char *lpszSNArray[], UINT16 DIPArray[], int nNumDevices );

wie muß ich das hier machen??

es wird nachher in C++ verwendet wie folgt
/*------------------------------------------------------------------------*/
unsigned short NumberDevices = 0;
/* Force the API to look for devices on the network */
KMTCPRefreshDevices();
/* Get the number of devices found on serial and/or Ethernet */
KMTCPGetNumDevices(&NumberDevices);
/* Initialize the array to retrieve all device names, */
/* serial numbers, and IP addresses */
char **NameArray= new char*[NumberDevices];
char **IPArray = new char*[NumberDevices];
char **SNArray = new char*[NumberDevices];
UINT16 *DIPArray = new UINT16[NumberDevices];
for(int j=0;j<NumberDevices;j++)
{
NameArray[j]=new char[MAX_TCP_NM_LENGTH];
IPArray[j]=new char[MAX_TCP_IP_LENGTH];
SNArray[j]=new char[MAX_TCP_SN_LENGTH];
}
/* Retrieve the device information */
KMTCPGetDeviceInformation(NameArray, IPArray, SNArray, DIPArray,
NumberDevices);
/*------------------------------------------------------------------------*/

und wie muß ich das dan verwenden??

ich hoffe mir kann jemand helfen

Gruß Stefan

Stevie 11. Jan 2005 10:38

Re: habe DLL aber nur C++ und VB Beispiele
 
Hi Stefan,

diese char-Pointer-Arrays sind in Delphi folgendermaßen zu deklarieren:
Delphi-Quellcode:
TDynPCharArray = array of PChar;
und das UINT16-Array so:
Delphi-Quellcode:
TDynWordArray = array of Word;
also sähe die Methode-Deklaration folgendermaßen aus:
Delphi-Quellcode:
function KMTCPGetDeviceInformation(NameArray, AddressArray, SNArray: TDynPCharArray; DIPArray: TDynWordArray; NumDevices: Integer); cdecl; external 'KmApi32.dll';
MfG
Stevie

P.S. Code-Tags würden deinen Beitrag etwas besser lesbar machen.

Robert Marquardt 11. Jan 2005 12:30

Re: habe DLL aber nur C++ und VB Beispiele
 
Sorry Stevie, komplett falsch. "array of" ist nie zu einem C Typ kompatibel.

Delphi-Quellcode:
type
  PPChar = ^PChar;
  UINT16 = Word;
  PUInt16 = ^UINT16;

function KMTCPGetDeviceInformation(lpszNameArray: PPChar; lpszAddressArray: PPChar; lpszSNArray: PPChar; DIPArray: PUINT16; nNumDevices: Integer): KMErrorCode; cdecl;
Entweder gibt nNumDevices die Laenge der Arrays von PChars bzw UINT16 an oder die Arrays werden durch einen PChar = nil abgeschlossen.

Stevie 11. Jan 2005 13:02

Re: habe DLL aber nur C++ und VB Beispiele
 
Zitat:

Zitat von Robert Marquardt
Sorry Stevie, komplett falsch.

*sichvorschamimstaubwälz* :oops: ich werd mich nie mit c anfreunden...

alf.stefan 11. Jan 2005 13:48

Re: habe DLL aber nur C++ und VB Beispiele
 
danke robert

weil mit dem Vorschlag von Stevie hatte ich so meine Probleme
aber mit den PPChar hab ich auch meine Probleme wie soll ich das denn initialisieren?
habs mal so versucht
Code:
   err := KMInitialize;
   NumDevices :=0;
   refresh := KMTCPRefreshDevices();
   getNum := KMTCPGetNumDevices(@NumDevices);
   if getNum = 0 then
   begin
      erg := 'Controllers Found '+IntToStr(NumDevices);
      for lLoop := 0 to NumDevices-1 do
      begin
        sNames^[lLoop] := '                                  ';
        sIP^[lLoop] := '                                  ';
        sSerStr^[lLoop] := '                                  ';
      end;
      err := KMTCPGetDeviceInformation(sNames, sIp, sSerStr, sDipArray, NumDevices);
   end;
aber so geht das nicht aber ich weiß auch gar nicht wie ich das überhaupt anpacken soll mit dem init?
ist das nicht sowas wie eine pointer liste?

ratloser Gruß
Stefan

Robert Marquardt 11. Jan 2005 16:06

Re: habe DLL aber nur C++ und VB Beispiele
 
Man sollte den Namen der Funktion lesen. Es werden offensichtlich eine Menge Puffer ausgefuellt.
Entsprechend ist der Parameter ein "Buffers: array [0..WASAUCHIMMER] of PChar" und jeder PChar muss seinerseits einen Puffer alloziiert haben.
Vermutlich steht in der Dokumentation wie lang so ein Name maximal sein kann.
Der Aufruf ist dann "KMTCPGetDeviceInformation(@Buffers[0], ...)"
Alternativ kann es sein das in Buffers nur Zeiger auf die intern vorgehaltenen Namen abgelegt werden.
Dann ist es nicht noetig die Elemente zu alloziieren, sondern man sollte dann die Elemente mit nil belegen.
Da kann aber nur die Dokumentation weiterhelfen.

Robert Marquardt 11. Jan 2005 16:12

Re: habe DLL aber nur C++ und VB Beispiele
 
Zitat:

Zitat von Stevie
ich werd mich nie mit c anfreunden...

Sachade, denn es ist definitiv die interessantere Sprache.
Ich habe zuerst C gelernt und bin froh darueber.
Im Gegensatz zum Durchschnitts-Pascal-Programmierer lernt man naemlich was ein Zeiger ist.

Gerade habe ich mal wieder eine besonders lustige Variablendeklaration in C anbringen koennen.

extern const volatile unsigned long int * const SomePointer;

Wer diese durchaus sinnvolle Deklaration entraetseln kann der gewinnt meine Hochachtung.

alf.stefan 11. Jan 2005 16:18

Re: habe DLL aber nur C++ und VB Beispiele
 
Danke einstweilenwerde das morgen gleich mal probieren.

Gruß Stefan

Chewie 11. Jan 2005 17:42

Re: habe DLL aber nur C++ und VB Beispiele
 
Zitat:

Zitat von Robert Marquardt
extern const volatile unsigned long int * const SomePointer;

Wer diese durchaus sinnvolle Deklaration entraetseln kann der gewinnt meine Hochachtung.

Leicht Offtopic, aber naja...
Was du da machst, ist einen Zeiger zu deklarieren, bei dem weder der Wert des Zeigers noch der Wert des Datums, auf der der Zeiger zeigt, innerhalb des Programm verändert werden kann, wohl aber von außen. Sinn machen würde das ganze, wenn du einen Wert, der z.B. per Interrupt gesetzt wurde, in deinem Programm verfügbar machen wilsst und dabei 100% sichergehen musst (naja, 100%ige Sicherheit hast du wohl nie), dass der Wert nicht verfälscht wird.
Aber wozu man das braucht, fällt mir auch nicht ein :?

Robert Marquardt 11. Jan 2005 19:23

Re: habe DLL aber nur C++ und VB Beispiele
 
Hochachtung!
Brauchen kann man das natuerlich. Wie waere es mit einer Interrupt Tabelle in einem Mikrocontroller?

Chewie 11. Jan 2005 19:37

Re: habe DLL aber nur C++ und VB Beispiele
 
Zitat:

Zitat von Robert Marquardt
Hochachtung!
Brauchen kann man das natuerlich. Wie waere es mit einer Interrupt Tabelle in einem Mikrocontroller?

Danke ;)
Nun, ich hab bisher leider nur mit hardwareabstrahierter Programmierung auf PCs Erfahrung und leider nicht mit µCs :?

Aber OK; jetzt wirklich zurück zum Thema!

alf.stefan 12. Jan 2005 07:49

Re: habe DLL aber nur C++ und VB Beispiele
 
Ich hab da immer noch meine Probleme!
Mach ich die Initialisierung richtig?

Code:
 
var
  nBuff : array of PChar;
  ipBuff : array of PChar;
  SerStrBuff : array of PChar;
  DipArrayBuff : array of PUint16;
  name : Array[0..MAX_TCP_NM_LENGTH] of pChar;
  ip: Array[0..MAX_TCP_IP_LENGTH] of pChar;
  ser: Array[0..MAX_TCP_SN_LENGTH] of pChar;
  ppName, ppIp, ppSer : pPchar;
begin
   err := KMInitialize;
   NumDevices :=0;
   refresh := KMTCPRefreshDevices();
   getNum := KMTCPGetNumDevices(@NumDevices);

   SetLength(nBuff, NumDevices);
   SetLength(ipBuff, NumDevices);
   SetLength(serStrBuff, NumDevices);
   SetLength(DipArrayBuff, NumDevices);

   for lLoop := 0 to NumDevices-1 do
   begin
      for c:= 0 to MAX_TCP_NM_LENGTH do name[c] := new(pChar);
      nBuff[lLoop] := name[0];
      for c:= 0 to MAX_TCP_IP_LENGTH do ip[c] := new(pChar);
      ipBuff[lLoop] := ip[0];
      for c:= 0 to MAX_TCP_SN_LENGTH do ser[c] := new(pChar);
      serStrBuff[lLoop] := ser[0];
      DipArrayBuff[lLoop] := new(PUint16);
   end;

   ppName := @nBuff[0];
   ppIp := @ipBuff[0];
   ppSer := @serStrBuff[0];
   if getNum = 0 then
   begin
      err := KMTCPGetDeviceInformation(ppName, ppIp, ppSer, DipArrayBuff[0], NumDevices);
   end;
Beim Compilieren kommt kein Fehler zurück
Beim debugen ist mir aber aufgefallen, daß in nBuff[0] keine Adresse steht! Obwohl es da eigentlich eine
Geben müßte.

Wieder ratloser Gruß

Stefan

alf.stefan 12. Jan 2005 08:20

Re: habe DLL aber nur C++ und VB Beispiele
 
Und es geht doch. Ich war schon ganz dicht an der Lösung.
Mein Fehler war ein var in der Funktions deklaration.

Code:
     Function KMTCPGetDeviceInformation(var lpszNameArray,lpszAddressArray,lpszSNArray: PPChar ;DIPArray: PUInt16 ;nNumDevices :long): KMErrorCode; cdecl; external 'KmApi32.DLL';
ohne das var gings dann plötzlich!

Danke an alle Beteiligten

Erleichterter Gruß

Stefan

Robert Marquardt 12. Jan 2005 09:02

Re: habe DLL aber nur C++ und VB Beispiele
 
Das "var" hatte ich auch nicht geschrieben.
Die Initialisierungen sind noch Murks.
Schmeiss alles was sich auf array of bezieht weg. Also nBuff, die lLoop-Schleife und die SetLength Aufrufe.
Offensichtlich liefert die Funktion in name usw PChars ab.
ppName usw wird auch nicht gebraucht. Direkt @name[0] usw als Parameter benutzen.

Die Funktion braucht ein array von PChar's, die auch wirklich im Speicher vorhanden sind.
"name" und Konsorten erfuellt das, denn das Array ist auf dem Stack vorhanden.

Die Deklaration von KMTCPGetNumDevices mit "var" statt Zeiger umschreiben, dann kann man
KMTCPGetNumDevices(NumDevices);
benutzen.

Boombuler 12. Jan 2005 09:33

Re: habe DLL aber nur C++ und VB Beispiele
 
kurze Frage am Rande:
PChar = Pointer auf Char
PPChar = Pointer auf PChar = Pointer auf Pointer auf Char???
Hat das n speziellen grund das ihr das so macht?

Greetz
Boombuler

alf.stefan 12. Jan 2005 09:40

Re: habe DLL aber nur C++ und VB Beispiele
 
Vielleicht ist es Murks aber es funktioniert.

Zitat:

Die Deklaration von KMTCPGetNumDevices mit "var" statt Zeiger umschreiben, dann kann man
KMTCPGetNumDevices(NumDevices);
benutzen.
das geht klar und funktioniert wunderbar

aber was ich nicht verstehe ist @name[0] ist doch der Zeiger auf nur einen Namen. Was ist wenn ich mehrere
devices habe NumDevices>1 ?
Deshalb habe ich das mit den dynamischen arrays ja so gemacht, daß NumDevices variabel sein kann.
Brauche ich dann nicht genau soviel Pointer auf die unterscheidlichen name[lLoop] wie es devices gibt?
enspricht das dann nicht so in etwa dem was auch in C++ gemacht wurde
Code:
/* serial numbers, and IP addresses */
char **NameArray= new char*[NumberDevices];
char **IPArray = new char*[NumberDevices];
char **SNArray = new char*[NumberDevices];
UINT16 *DIPArray = new UINT16[NumberDevices];
for(int j=0;j<NumberDevices;j++)
{
NameArray[j]=new char[MAX_TCP_NM_LENGTH];
IPArray[j]=new char[MAX_TCP_IP_LENGTH];
SNArray[j]=new char[MAX_TCP_SN_LENGTH];
oder wie sollte ich das namens array (also nicht name[0]..) anders initialisieren.

Code:
   ppName := @nBuff[0];
   ppIp := @ipBuff[0];
   ppSer := @serStrBuff[0];
das ist natürlich murks und müll, das hab ich auch gleich selbst gelöscht und dann
Code:
KMTCPGetDeviceInformation(@nBuff[0], @ipBuff[0], @serStrBuff[0], DipArrayBuff[0], NumDevices);
direkt aufgerufen.

Verwirrter Gruß

Stefan

alf.stefan 12. Jan 2005 09:48

Re: habe DLL aber nur C++ und VB Beispiele
 
ja das hat es. C++ ruft das halt auch so auf.
Musst Dir mal bei meiner 1. Frage den C++ code anschauen wie da vor dem Funtionsauruf die arrays initialisiert werden.

Code:
char **NameArray= new char*[NumberDevices];
char **IPArray = new char*[NumberDevices];
char **SNArray = new char*[NumberDevices];
und das muß in Delphi dann halt auch so ähnlich genacht werden damit man die Funktion benutzen kann.
Aber der Oberblicker bin ich da auch nicht.

Robert Marquardt 12. Jan 2005 11:41

Re: habe DLL aber nur C++ und VB Beispiele
 
Die C Deklaration lautet "char *name[]". Das ist praktisch das selbe wie "char **name".
Die feinen Unterschiede wollen wir hier nicht waelzen.
Also lautet die Pascal Deklaration korrekt PPChar eben ein Zeiger auf einen Zeiger auf Char.
C kennt nur call by value. Call by reference wird genau durch "Zeiger auf" repraesentiert.
Das ist das was Pascal bei var-Parametern auch macht.
Ueblicherweise gilt bei der Uebergabe eines Arrays in C das der Zeiger auf das erste Element des Arrays uebergeben wird.
Die Groesse des Arrays muss in einem gesonderten Parameter uebergeben werden.
Alternativ wird der letzte Zeiger des Arrays auf nil gesetzt um das Ende anzuzeigen.
"char *name[]" ist also ein Array von PChars.

alf.stefan 12. Jan 2005 12:32

Re: habe DLL aber nur C++ und VB Beispiele
 
das ist ja alles schön und gut und richtig. Aber wie soll ich denn dann
"char *name[]" initialisieren wenn nicht so wie ich es gemacht habe.
Möglich, daß ich mich auch bloss blöd anstelle aber ich hab keine Ahnung wie ich es anders machen könnte.
Aber es ist auch möglich, daß ich dadurch wie ich es gemacht habe mein nächstes Problem erzeugt habe,
nämlich wie im Thread "immer noch Stress mit DLL Aufruf" beschrieben der Absturz beim Zugreifen auf meine
eingelesenen PPChar arrays.

Immer noch einigermassen ratloser Gruß

Stefan

Sprint 12. Jan 2005 13:39

Re: habe DLL aber nur C++ und VB Beispiele
 
Hallo Stefan,

solltest du nicht weiterkommen, dann kannst du mir die VB-Deklarationen schicken. Ich helfe dir dann beim Übersetzen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:25 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz