hytham
hytham

Reputation: 53

How to initiate the com port using MetroCom.dll in delphi

I write a code in Delphi to initiate the com port that connected to my device and I get an Error access violation at address 0x0000 the code I write is:

unit Test_Cam;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TByteArr = array of byte;
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    ComboBox1: TComboBox;



    procedure Button1Click(Sender: TObject);
    procedure Doconnect;
    procedure CamOpen;
    Function StrToByte(const Value: String): TByteArr;
  private
    { Private declarations }


  public
  published
    property ObjectMenuItem;
    { Public declarations }
  end;
  TconfigPort = record
    BaudRate:Integer; // baud rate
    ByteSize:Integer; // number of bits/byte, 4-8
    Parity:Integer; // 0-4=no,odd,even,mark,space
    StopBits:Integer; // 0,1,2 = 1, 1.5, 2
    fOutxCtsFlow:Integer; // CTS Flow Control
  end;

  TPROGRESS_FUNC = procedure (blocks_total,blocks_done:Integer) of Object;

var
  Form1: TForm1;

  Function MetrocomEnterImageUpl(nport:Integer):Boolean; external 'metrocom.dll';
  procedure MetrocomAcquireFullFrame(nport:Integer); external 'metrocom.dll';


  Function MetrocomUploadJpeg(nPort:Integer; PROGRESS_FUNC:Tprogress_func; szFileName:string; nSubsampling:integer):Boolean; external 'metrocom.dll';
  Function MetrocomExitImageUpl(nPort:Integer):Boolean; external 'metrocom.dll';
  Function MetrocomInitCommunication(nPort:Integer; COMMPORTCONFIG:TconfigPort):Boolean; external 'metrocom.dll';
  Function MetrocomEndCommunication(nPort:Integer):Boolean; external 'metrocom.dll';
  Function camSetImageCompression(cam_handle:Integer; quality:Integer; method:Integer):Integer; external 'Camlib.dll';
  Function camSetCenteredWOI(cam_handle:Integer;img_width:Integer;img_height:Integer):Integer; external 'Camlib.dll';
  Function camInit(dev_interface:Integer):Integer; external 'Camlib.dll';
  Function camOpenEx2(device_name:TByteArr;ctl_bus_name:Byte;Var p_dev_type:Integer; ctl_bus_type:integer; camera_type:integer;dev_bus_type:Integer):Integer; external 'Camlib.dll';
  Function camClose(cam_handle:Integer):Integer; external 'Camlib.dll';
  Function camFree:Integer; external 'Camlib.dll';
  Function camGetOperatingMode(cam_handle:Integer; var mode:Integer):Integer; external 'Camlib.dll';

var
  Config_port: TconfigPort;
  m_bConnect:Boolean = false;
  m_nPort,m_nInit,nPort,i,j,m_camHandle:integer;
  nDeviceType:Integer = 0;
  device_name:string;
  szDeviceName:TByteArr;

implementation

{$R *.dfm}

function TForm1.StrToByte(const Value: String): TByteArr;
var
    I: integer;
begin
    SetLength(Result, Length(Value));
    for I := 0 to Length(Value) - 1 do
        Result[I] := ord(Value[I + 1]) ;
end;

procedure Tform1.DoConnect;
begin
 m_nPort := StrToInt(ComboBox1.Text) - 1;
 Config_port.BaudRate := 9600;
 Config_port.ByteSize := 8;
 Config_port.Parity := 0;
 Config_port.StopBits := 0;
 m_bConnect := MetrocomInitCommunication(m_nPort , Config_port);
end;

procedure TForm1.CamOpen;
begin
 m_nInit := camInit(0);
 if m_nInit < 0  then
    ShowMessage('Fail to camInit.');
 nPort := m_nPort + 1;
 device_name := 'COM' + IntToStr(nPort) + ' baud=' + IntToStr(Config_port.BaudRate) + ' parity=' + IntToStr(Config_port.Parity) + ' data=' + IntToStr(Config_port.ByteSize) + ' stop=' + IntToStr(Config_port.StopBits);
 szDeviceName := strtobyte(device_name);
 for i := 0 to 4 do
  begin
   for j := 0 to 4 do
    begin
     m_camHandle := camOpenEx2(szDeviceName, 0 ,  nDeviceType, 0, 1, 0);
     if m_camHandle < 0 then break;
    end;
   if m_camHandle < 0 then break;
  end;

end;


procedure TForm1.Button1Click(Sender: TObject);
begin
 DoConnect;
 CamOpen;
 camSetImageCompression(m_camHandle, 30, 0);
 camSetCenteredWOI(m_camHandle, 500, 220);

end;

end.   

and the documentation for the DLL file is:

MetrocomInitCommunication
Purpose:
Open the port for communication and set up the ports parameters. The communication parameters only
matter when a real COM port is used  for either USB or Bluetooth virtual COM ports these settings are
ignored.
C/C++:
BOOL MetrocomInitCommunication(int i_port, COMMPORTCONFIG * p_config);
Visual Basic:
Declare Function MetrocomInitCommunication Lib "metrocom.dll" _ 
    (ByVal i_port As Long, ByRef config As COMMPORTCONFIG) As Long 
Parameters:
i_port - [in] Communication port number (0 for COM1, 1 for COM2, etc.)
p_config - [in] Port configuration structure  this parameter sets baud rate and other port settings to be
used during normal communication (not during image upload)
Return value:
1 if the parameters were set successfully and the port was opened, 0 otherwise.

Upvotes: 2

Views: 486

Answers (1)

David Heffernan
David Heffernan

Reputation: 613242

The calling convention for your imported functions is incorrect. You did not specify a calling convention, so the default register conventions is used. Consult the documentation to find out what calling convention is used.. The VB6 declaration you give uses stdcall, so that's where my money lies. All VB6 imports are stdcall. When translating headers, always ensure the calling convention is specified correctly

After you fix that there will be many more problems with the interop. The use of of object is clearly wrong. A C++ library will not implement that. Also wrong is the use of Delphi string. Strings will likey be passed as C strings, pointers to null-terminated character arrays. And the structs will probably be passed by reference rather than value.

For the function in question, the C++ declaration makes it clear that the struct is passed by reference.

The function should be declared like this:

function MetrocomInitCommunication(
    nPort: Integer; 
    const config: TConfigPort
): BOOL; stdcall; external 'metrocom.dll';

Upvotes: 3

Related Questions