I have a code in Delphi I using the it to get picture from my 2D Reader, I am using 'camlib.dll' to set parameter of the Image in the device the code:
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; stdcall; external 'metrocom.dll';
Function MetrocomExitImageUpl(nPort:Integer):Boolean; stdcall; external 'metrocom.dll';
Function MetrocomInitCommunication(nPort:Integer; const COMMPORTCONFIG:TconfigPort):Boolean;stdcall; external 'metrocom.dll';
Function MetrocomEndCommunication(nPort:Integer):Boolean; stdcall; external 'metrocom.dll';
Function camSetImageCompression(cam_handle:Integer; quality:Integer; method:Integer):Integer;stdcall; external 'Camlib.dll';
Function camSetCenteredWOI(cam_handle:Integer;img_width:Integer;img_height:Integer):Integer; stdcall; external 'Camlib.dll';
Function camInit(dev_interface:Integer):Integer; stdcall; external 'Camlib.dll';
Function camOpenEx2(device_name:TByteArr;ctl_bus_name:TByteArr;Var p_dev_type:Integer; ctl_bus_type:integer; camera_type:integer;dev_bus_type:Integer):Integer; stdcall; external 'Camlib.dll';
Function camClose(cam_handle:Integer):Integer; stdcall; external 'Camlib.dll';
Function camFree:Integer; stdcall; external 'Camlib.dll';
Function camGetOperatingMode(cam_handle:Integer; var mode:Integer):Integer; stdcall; external 'Camlib.dll';
var
Config_port: TconfigPort;
m_bConnect:Boolean = false;
tt,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, nil , nDeviceType, 0, 1, 16);
if m_camHandle > 0 then break;
end;
if m_camHandle > 0 then break;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DoConnect;
CamOpen;
tt := camSetImageCompression(m_camHandle, 30, 2);
camSetCenteredWOI(m_camHandle, 500, 220);
end;
end.
I get an Erorr in this line and the error occurred after the tow functions is compiled I get an error that 'access violation at 0x000001f4:read of address 0x000001f4' and then opend the CPU debuging in delphi:
tt := camSetImageCompression(m_camHandle, 30, 2);
camSetCenteredWOI(m_camHandle, 500, 220);
the description of the function in camlib.dll is:
camSetImageCompression
This function sets the image compression parameters.
Prototype:
int camSetImageCompression (int cam_handle, int quality, int method);
Parameters:
cam_handle - [in] handle to the camera device returned by the camOpen function.
quality - [in] allowable value of image quality after compression: 1(worst) - 100(best)
method - [in] allowable compression method. Currently, this parameter can be one of the
following values:
CAMLIB_COMPRESS_NONE no compression;
CAMLIB_COMPRESS_SUBSAMPLE image resampling down;
CAMLIB_COMPRESS_JPEG JPEG compression;
CAMLIB_COMPRESS_ANY any method of compression;
Return Value:
0: Success; -1: Failure
camSetCenteredWOI
This function sets the window of interest (WOI) of the given size centered horizontally and vertically in the
field of view of the camera.
Prototype:
int camSetCenteredWOI (int cam_handle, int img_width, int img_height);
Parameters:
cam_handle - [in] handle to the camera device returned by the camOpen function.
img_width - [in] image width, in pixels.
img_height - [in] image height, in rows.
Return Value:
0: Success; -1: Failure
camOpenEx2
This function establishes communication with the specified camera device.
Prototype:
int camOpenEx2 (char *device_name, char *ctl_bus_name, int *p_dev_type, int ctl_bus_type,
intcamera_type, int dev_bus_type);
Parameters:
device_name - [in] camera communication device name optionally followed by a device-control
string that contains communication parameters. Currently, the device name must
be a valid serial port. For example, the following string specifies the COM1
communication port, a baud rate of 9600, no parity, 8 data bits, and 1 stop bit:
COM1: baud=9600 parity=N data=8 stop=1. If the communication device is USB
then the device_name parameter should be 0.
ctl_bus_name - [in] should be NULL.
p_dev_type - [out] (optional) pointer to the location where the function returns the type of image
sensor used in the camera. Currently, this value can only be
CAM_IMG_SENSOR_MT9M001C or CAM_IMG_SENSOR_VC5602 (or
CAM_IMG_SENSOR_UNKNOW N if the sensor type could not be automatically
identified).
ctl_bus_type - [in] should be 0.
camera_type - [in] camera type. Currently, this value can only be
CAMLIB_CAMERATYPE_FOCUS, CAMLIB_CAMERATYPE_ORBIT3 or
CAMLIB_CAMERATYPE_VUQUEST.
dev_bus_type - [in] device bus type. Currently, this value can only be CAMLIB_BUSTYPE_RS232
or CAMLIB_BUSTYPE_USB20.
Return Value:
If positive handle to the camera device, or (-1) in case of error. The handle must be used in all
consequent calls to CamLib APIs to identify the camera device on which an operation is requested
to be performed.
in C# it is working fine:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
namespace Sample
{
public partial class frmMain : Form
{
public struct COMMPORTCONFIG
{
public int BaudRate; // baud rate
public int ByteSize; // number of bits/byte, 4-8
public int Parity; // 0-4=no,odd,even,mark,space
public int StopBits; // 0,1,2 = 1, 1.5, 2
int fOutxCtsFlow; // CTS Flow Control
}
[DllImport(@"C:\WINDOWS\metrocom.dll", EntryPoint = "MetrocomEnterImageUpl")]
extern public static bool MetrocomEnterImageUpl(int nPort);
[DllImport(@"C:\WINDOWS\metrocom.dll", EntryPoint = "MetrocomAcquireFullFrame")]
extern public static void MetrocomAcquireFullFrame(int nPort);
public delegate void PROGRESS_FUNC(int blocks_total, int blocks_done);
[DllImport(@"C:\WINDOWS\metrocom.dll", EntryPoint = "MetrocomUploadJpeg")]
extern public static bool MetrocomUploadJpeg(int nPort, PROGRESS_FUNC p_progress_func, char[] szFileName, int nSubsampling);
[DllImport(@"C:\WINDOWS\metrocom.dll", EntryPoint = "MetrocomExitImageUpl")]
extern public static bool MetrocomExitImageUpl(int nPort);
[DllImport(@"C:\WINDOWS\metrocom.dll", EntryPoint = "MetrocomInitCommunication")]
extern public static bool MetrocomInitCommunication(int nPort, ref COMMPORTCONFIG p_config);
[DllImport(@"C:\WINDOWS\metrocom.dll", EntryPoint = "MetrocomEndCommunication")]
extern public static bool MetrocomEndCommunication(int nPort);
[DllImport(@"C:\WINDOWS\Camlib.dll", EntryPoint = "camSetImageCompression")]
extern public static int camSetImageCompression(int cam_handle, int quality, int method);
[DllImport(@"C:\WINDOWS\Camlib.dll", EntryPoint = "camSetCenteredWOI")]
extern public static int camSetCenteredWOI(int cam_handle, int img_width, int img_height);
[DllImport(@"C:\WINDOWS\Camlib.dll", EntryPoint = "camInit")]
extern public static int camInit(int dev_interface);
[DllImport(@"C:\WINDOWS\Camlib.dll", EntryPoint = "camOpenEx2")]
public extern static int camOpenEx2(byte[] device_name, byte[] ctl_bus_name, ref int p_dev_type, int ctl_bus_type, int camera_type, int dev_bus_type);
[DllImport(@"C:\WINDOWS\Camlib.dll", EntryPoint = "camClose")]
extern public static int camClose(int cam_handle);
[DllImport(@"C:\WINDOWS\Camlib.dll", EntryPoint = "camFree")]
extern public static int camFree();
[DllImport(@"C:\WINDOWS\Camlib.dll", EntryPoint = "camGetOperatingMode")]
extern public static int camGetOperatingMode(int cam_handle, ref int mode);
//[DllImport(@"C:\WINDOWS\Camlib.dll", EntryPoint = "camReadData")]
//extern public static int camReadData (int cam_handle, int ibus,
// char *buf,int cb_to_read, int *cb_read,int *fcancel, long ms_timeout, long ms_idle_timeout);
[DllImport(@"C:\WINDOWS\metrocom.dll", EntryPoint = "MetrocomReadData")]
extern public static bool MetrocomReadData(long i_port, string buf, long dw_bufsize, long fcancel,
long wait_timeout, long read_timeout);
[DllImport(@"C:\WINDOWS\GetSN.dll", EntryPoint = "CheckValid")]
extern public static bool CheckValid();
int m_nPort = -1;
COMMPORTCONFIG p_config = new COMMPORTCONFIG();
int m_camHandle = -1;
int m_nInit = -1;
bool m_bConnect = false;
string m_strPath = System.IO.Directory.GetCurrentDirectory();
int m_nMode = -1;
public frmMain()
{
InitializeComponent();
}
private void Connect_Click(object sender, EventArgs e)
{
if (Connect.Text.Trim() == "connect")
{
DoConnect();
CamOpen();
IsConnet();
camSetImageCompression(m_camHandle, 30, 0x002);
camSetCenteredWOI(m_camHandle, 500, 220);
Shapshot.Enabled = true;
textBox1.Focus();
//Shapshot_Click(sender, e);
}
else
{
DoDisconnect();
CamCloe();
}
}
private void Shapshot_Click(object sender, EventArgs e)
{
if (textBox1.Text.Trim() == "")
{
MessageBox.Show("chose the name please");
textBox1.Focus();
}
else
{
GetOperatingMode();
if (m_nMode == 0)
{
PROGRESS_FUNC test = new PROGRESS_FUNC(progress_function);
bool bResult = MetrocomEnterImageUpl(m_nPort);
MetrocomAcquireFullFrame(m_nPort);
//string strPath = Application.ExecutablePath;
string strFileName = m_strPath + "\\" + textBox1.Text + "1.jpg";
char[] szFileName = strFileName.ToCharArray(0, strFileName.Length);
bool bTemp = false;
if (bResult)
bTemp = MetrocomUploadJpeg(m_nPort, test, szFileName, 0);
}
MetrocomExitImageUpl(m_nPort);
if (MessageBox.Show("another Side ", "Take picture",
MessageBoxButtons.OKCancel, MessageBoxIcon.Question)
== DialogResult.OK)
{
GetOperatingMode();
if (m_nMode == 0)
{
PROGRESS_FUNC test = new PROGRESS_FUNC(progress_function);
bool bResult = MetrocomEnterImageUpl(m_nPort);
MetrocomAcquireFullFrame(m_nPort);
//string strPath = Application.ExecutablePath;
string strFileName = m_strPath + "\\" + textBox1.Text + "2.jpg";
char[] szFileName = strFileName.ToCharArray(0, strFileName.Length);
bool bTemp = false;
if (bResult)
bTemp = MetrocomUploadJpeg(m_nPort, test, szFileName, 0);
}
textBox1.Text = "";
}
}
}
private void frmMain_Load(object sender, EventArgs e)
{
string[] szArray = new string[256];
for (int i = 0; i < szArray.Length; i++)
{
szArray[i] = "Com" + i;
}
cmbPort.DataSource = szArray;
cmbPort.SelectedIndex = 3;
bool valid = CheckValid();
if (valid == false)
{
Application.Exit();
}
}
private void DoConnect()
{
string strTemp = cmbPort.Text.Trim();
string[] parts = strTemp.Split('m');
m_nPort = Convert.ToInt16(parts[1]) - 1;
p_config.BaudRate = 9600;
p_config.ByteSize = 8;
p_config.Parity = 0;
p_config.StopBits = 0;
m_bConnect = MetrocomInitCommunication(m_nPort, ref p_config);
}
private void CamOpen()
{
m_nInit = camInit(0);
if (m_nInit < 0)
MessageBox.Show("Fail to connect");
int nPort = m_nPort + 1;
string device_name;
device_name = "COM" + nPort + " baud=" + p_config.BaudRate + " parity=" + p_config.Parity + " data=" + p_config.ByteSize + " stop=" + p_config.StopBits;
int nDeviceType = 0;
int i, j;
byte[] szDeviceName = System.Text.Encoding.Default.GetBytes(device_name);
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
m_camHandle = camOpenEx2(szDeviceName, null, ref nDeviceType, 0, 1, 0x0010);
if (m_camHandle > 0)
break;
}
if (m_camHandle > 0)
break;
}
}
private void CamCloe()
{
if (m_camHandle >= 0)
camClose(m_camHandle);
if (m_nInit == 0)
camFree();
}
private void DoDisconnect()
{
if (m_bConnect)
MetrocomEndCommunication(m_nPort);
Connect.Text = "connect";
cmbPort.Enabled = true;
}
private void IsConnet()
{
if (!m_bConnect || m_camHandle <= 0)
MessageBox.Show("Fail to connect to Fcous.", "UnitechVision");
else
{
cmbPort.Enabled = false;
Connect.Text = "connected";
}
}
private int GetOperatingMode()
{
camGetOperatingMode(m_camHandle, ref m_nMode);
return m_nMode;
}
void progress_function(int blocks_total, int blocks_done)
{
blocks_total = 30;
blocks_done = 50;
}
private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
{
if (m_camHandle > 0)
camClose(m_camHandle);
if (m_nInit == 0)
camFree();
if (m_bConnect)
MetrocomEndCommunication(m_nPort);
}
private void button1_Click(object sender, EventArgs e)
{
string s = @"d:\12\1.jpg";
pictureBox1.Load(s);
}
}
}
Your translations of camSetImageCompression
and camSetCenteredWOI
are accurate. There is nothing wrong there.
The problem is camOpenEx2
. There you use a Delphi managed dynamic array type. That's not valid for interop. Now, we cannot tell for sure what the C declaration for camOpenEx2
should be, but the name of your global variable szDeviceName
suggests very strongly that the text parameters are char*
, that is pointers to null-terminated arrays of 8 bit characters.
In which case you declare camOpenEx2
like this:
Function camOpenEx2(
device_name: PAnsiChar;
ctl_bus_name: PAnsiChar;
Var p_dev_type: Integer;
ctl_bus_type: Integer;
camera_type: Integer;
dev_bus_type: Integer
): Integer; stdcall; external 'Camlib.dll';
And you call it like this:
m_camHandle := camOpenEx2(PAnsiChar(DeviceName), nil, nDeviceType, 0, 1, 16);
Note that I am assuming that the rest of your declaration is correct. I cannot check because you did not show the C declaration of camOpenEx2
.
I also cannot be sure that passing nil
for the second parameter is valid. Perhaps you are expected to pass an empty string, in which case you would pass ''
. Update: The C# code seems to indicate that passing nil
is acceptable.
Note also that I am assuming you use a pre-Unicode Delphi. But if not, that is if you have Delphi 2009 or later, then you need to declare DeviceName
to be AnsiString
rather than string
.
Now, there may be other errors than this. This is interop and that requires a human to ensure that both sides of the interop interface match. You showed the other side for camSetImageCompression
and camSetCenteredWOI
and for sure your translations are accurate. For sure a dynamic array is incorrect for interop. But I cannot check any more than that since I can only see one side of the interop interface.
Update
The C# clears things up a little, but that code is wrong too. Specifically its use of byte and char arrays cannot be correct. I guess by chance the .net framework is allocating memory that happens to have null-terminators off the ends of the arrays.
I think that MetrocomUploadJpeg
looks dubious. That char[]
doesn't seem plausible. But you are not calling it so let's not get hung up on it. As for the rest of the imports, they match the p/invokes. Well, once you change camOpenEx2
as described above.
The C# code looks very flimsy to me. Frankly I think you are better working from the original documentation, and a C++ example. I've no idea where that C# code came from, but it's not well done.
User contributions licensed under CC BY-SA 3.0