如何使用delphi中的libcam.dll将参数发送到我的设备

时间:2013-10-02 15:59:47

标签: delphi winapi delphi-2006

我在Delphi中有一个代码我使用它来从我的2D阅读器获取图片,我使用'camlib.dll'来设置设备中Image的参数代码:

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.

我在这行中得到一个Erorr并且编译了两个函数后发生错误我得到一个错误,即“0x000001f4处的访问冲突:读取地址0x000001f4”然后在delphi中打开CPU debuging:

 tt := camSetImageCompression(m_camHandle, 30, 2);
 camSetCenteredWOI(m_camHandle, 500, 220);

camlib.dll中函数的描述是:

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.

在C#中工作正常:

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);

        }


    }
}

1 个答案:

答案 0 :(得分:1)

camSetImageCompressioncamSetCenteredWOI的翻译准确无误。那里没有错。

问题是camOpenEx2。你使用Delphi管理的动态数组类型。这对互操作无效。现在,我们无法确定camOpenEx2的C声明应该是什么,但是全局变量szDeviceName的名称非常强烈地表明文本参数是char*,这是指向以null结尾的8位字符数组。

在这种情况下,您可以像这样声明camOpenEx2

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';

你这样称呼它:

m_camHandle := camOpenEx2(PAnsiChar(DeviceName), nil,  nDeviceType, 0, 1, 16);

请注意,我假设您声明的其余部分是正确的。我无法检查,因为您没有显示camOpenEx2的C声明。

我也无法确定第二个参数的nil传递是否有效。也许你应该传递一个空字符串,在这种情况下你会传递''更新: C#代码似乎表明传递nil是可以接受的。

另请注意,我假设您使用的是Unicode前Delphi。但如果没有,那就是如果你有Delphi 2009或更高版本,那么你需要将DeviceName声明为AnsiString而不是string

现在,可能还有其他错误。这是互操作的,并且需要人来确保互操作接口的两侧匹配。您展示了camSetImageCompressioncamSetCenteredWOI的另一面,并确保您的翻译准确无误。对于互操作,确保动态数组不正确。但我不能检查,因为我只能看到互操作界面的一面。

<强>更新

C#清除了一点,但代码也错了。具体来说,它对byte和char数组的使用是不正确的。我猜想.net框架偶然会分配内存,而这些内存恰好在数组的末尾有空终结符。

我认为MetrocomUploadJpeg看起来很可疑。那char[]似乎不合理。但是你没有打电话给它,所以不要挂断它。至于其余的导入,它们匹配p / invokes。好吧,如上所述更改camOpenEx2

C#代码看起来非常脆弱。坦率地说,我认为你最好从原始文档和C ++示例开始。我不知道C#代码来自哪里,但它做得不好。