PDA

Ver la Versión Completa : Funcion en DLL pasar de C++ a Delphi


cesarsoftware
28-03-2022, 17:22:57
Hola compañeros.
Estoy tratando de trasladar un codigo escrito en C++ que llama a funciones de una DLL a Delphi. El procedimiento basico esta hecho pero no comprendo o no se bien como pasar los parametros,
Escribo el codigo C++

struct MELDEVICEDATA
DWORD dwDeviceType; /* Device type (Set DEVICETYPE_TCP.) */
APIDEVICE uniDeviceInfo; /* Device information */

struct APIDEVICE
struct Tcp
char IPAddr[16]; /* IP address (e.g. “192.168.100.1”) */
long lPortNo; /* Port No. (Set 683 (fixed value).) */
char dummy[12]; /* Reserved */

DWORD WINAPI melIoctl( HWND hWnd, long lAddress, long lFunction, LPVOID lpData ); ): Longint; stdcall; /* function in DLL */

void setmachine; {
/* Set IP address */
MELDEVICEDATA MelIoctlData;
long lIPAdrLen;
char szIPAddress[] = "192.168.100.1";
DWORD dwStatus;
/* Set device type */
melIoctlData.dwDeviceType = DEVICETYPE_TCP;
/* Set IP address */
lIPAdrLen = strlen(szIPAddress);
strncpy(MelIoctlData.uniDeviceInfo.Tcp.IPAddr, szIPAddress, lIPAdrLen);
melIoctlData.uniDeviceInfo.Tcp.IPAddr[lIPAdrLen] = '\0';
/* Set port No. */
MelIoctlData.uniDeviceInfo.Tcp.lPortNo = 683;
dwStatus = melIoctl(NULL, ADR_MACHINE(1), DEV_SET_COMMADDRESS, &MelIoctlData);
}


Y ahora el codigo Delphi que casi seguro no esta bien.

type APIDEVICE = record
IPAddr: ansistring; // IP address (e.g. “192.168.100.1”)
lPortNo: word; // Port No. (Set 683 (fixed value).)
dummy: array[0..11] of UINT16; // array of supported bus controllers
end;

type MELDEVICEDATA = packed record
dwDeviceType: LongWord; // Device type (Set DEVICETYPE_TCP.)
uniDeviceInfo: APIDEVICE; // Device information
end;

type tMELDEVICEDATA = ^MELDEVICEDATA;

function melIoctl(HWND, lAddress, lFunction: LongWord; lpData: Pointer): LongWord; cdecl; stdcall; external 'ncap.iDLL';

procedure TForm1.BotonProbarClick(Sender: TObject);
var
MelIoctlData: tMELDEVICEDATA;
szIPAddress: ansistring;
dwStatus: LongWord;
begin
StaticText1.Caption := '';
StaticText1.Update;
New(MelIoctlData);
szIPAddress := AnsiString(EditCncIP.Text);
MelIoctlData^.dwDeviceType := DEVICETYPE_TCP;
MelIoctlData^.uniDeviceInfo.IPAddr := szIPAddress;
MelIoctlData^.uniDeviceInfo.lPortNo := 683;
dwStatus := melIoctl(Self.Handle, ADR_MACHINE, DEV_SET_COMMADDRESS, tMELDEVICEDATA(MelIoctlData));
// function melIoctl(HWND: LongWord; var lAddress, lFunction: LongWord; const lpData: string): Longint; stdcall;
StaticText1.Caption := IntToStr(dwStatus);
if dwStatus = ME_SYSFUNC_IOCTL_ADDR then // Address error
Beep
else
if dwStatus = ME_SYSFUNC_IOCTL_FUNCTION then // Function error
Beep
else
Beep;
Dispose(tMELDEVICEDATA(MelIoctlData));
end;


Si alguien es tan amable de ayudarme, lo agradecere ampliamente, cervezas incluidas

Neftali [Germán.Estévez]
29-03-2022, 12:19:08
Hola compañeros.
Estoy tratando de trasladar un codigo escrito en C++ que llama a funciones de una DLL a Delphi.
...
Y ahora el codigo Delphi que casi seguro no esta bien.

Tendías que explicar qué problema hay.
¿No compila? ¿No funciona en ejecución?

Aun así hay referencias en ese código que no están disponibles por lo que también es difícil probarlo (DEVICETYPE_TCP, por ejemplo).

cesarsoftware
29-03-2022, 12:32:42
Buenas Netfali.
Que majo eres, siempre dispuesto a ayudar, Gracias.
El problema es que no se si es convertido bien la funcion, sobre todo por el tema del puntero a la estructura &MelIoctlData.
No da problema de compilacion, y la funcion me devuelve un error, con lo que en teoria, al menos, la libreria funciona y no "explota"
La constante DEVICETYPE_TCP debe estar en otro fichero que por cierto no encuentro, no se si sera un tipo fijo en algun include .H de linux.
De momento le he asignado un valor para salir del paso sabiendo que me falta esa constante.
Tambien veo que ADR_MACHINE es como un array para C++ pero como no se como pasarle ese "puntero" tambien he hecho mal y como es un longorwd le he puesto a 1 hasta aprender a mandarle ese tipo de array.
Las otras constantes si estan sacadas del manual del fabricante pero DEVICETYPE_TCP no esta en el manual y es un valor OBLIGADO Y NECESARIO por ellos. Algun dia lo encontrare o les llamare a los japaneses, jejeje.

const
DEVICETYPE_TCP: word = 1;
ADR_MACHINE: LongWord = 1;
DEV_SET_COMMADDRESS: LongWord = $FFF; // 4095
ME_SYSFUNC_IOCTL_FUNCTION: LongWord = $80020132; // Function error
ME_SYSFUNC_IOCTL_ADDR: LongWord = $80020190; // Address error

Como veras la funcion en C++ es:

dwStatus = melIoctl(NULL, ADR_MACHINE(1), DEV_SET_COMMADDRESS, &MelIoctlData);

Mi pregunta es, ¿asi esta bien convertida a Delphi?

dwStatus := melIoctl(Self.Handle, ADR_MACHINE, DEV_SET_COMMADDRESS, tMELDEVICEDATA(MelIoctlData));

¿He convertido bien las estructuras?

struct MELDEVICEDATA{
DWORD dwDeviceType; // Device type (Set DEVICETYPE_TCP.)
APIDEVICE uniDeviceInfo; // Device information
}
struct APIDEVICE {
struct Tcp {
char IPAddr[16]; // IP address (e.g. “192.168.100.1”)
long lPortNo; // Port No. (Set 683 (fixed value).)
char dummy[12]; // Reserved
}
}


type APIDEVICE = record
IPAddr: ansistring; // IP address (e.g. “192.168.100.1”)
lPortNo: word; // Port No. (Set 683 (fixed value).)
dummy: array[0..11] of UINT16; // array of supported bus controllers
end;

type MELDEVICEDATA = packed record
dwDeviceType: LongWord; // Device type (Set DEVICETYPE_TCP.)
uniDeviceInfo: APIDEVICE; // Device information
end;

type tMELDEVICEDATA = ^MELDEVICEDATA;


Espero ansiosamente tus comentos. ;?

Neftali [Germán.Estévez]
29-03-2022, 18:00:14
No soy especialista en C++.
Lo mueve al foro correspondiente a ver si alguien con más conocimientos te puede ayudar.

De todas formas un primer intento del que no te puedes fiar sería:

type
PTcp = ^Tcp;
PAPIDEVICE = ^APIDEVICE;
PMELDEVICEDATA = ^MELDEVICEDATA;

Tcp = record
IPAddr: array [0..15] of Char;
lPortNo: Integer;
dummy: array [0..11] of Char;
end;

APIDEVICE = record
ValueTcp: Tcp;
end;

MELDEVICEDATA = record
dwDeviceType: Integer;
uniDeviceInfo: APIDEVICE;
end;

cesarsoftware
29-03-2022, 18:08:55
Gracias German

Espero la ayuda de los expertos.
Siento no pasar tanto por el foro como antes, tengo mucho trabajo, pero intentare pasar por aqui mas a menudo para echar una mano.