Reputation: 53
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
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