Machsupport Forum
Mach Discussion => Mach4 General Discussion => Topic started by: rhtuttle on February 16, 2017, 02:48:29 PM
-
Thought I would throw out an example of how to connect and utilize Mach4's Mach4IPC.dll This dll contains all of the listed APIs. This example only has a few of those listed. Enough to demonstrate
This code would be used by any application:
unit Mach4DllWrapper;
interface
uses
Windows, Messages, SysUtils, Variants, Classes;
//define each function that you might call
type TmcIpcInit = function(ipAddr: pChar):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
type TmcGetInstance = function:integer;{$IFDEF WIN32} stdcall; {$ENDIF}
type TmcIpcCleanup = function:integer;{$IFDEF WIN32} stdcall; {$ENDIF}
type TmcRegGetValue = function( hReg:integer;value:pdouble):integer ;{$IFDEF WIN32} stdcall; {$ENDIF}
type TmcCntlLoadGcodeFile = function(mInst:integer;FileToLoad:pChar):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
Type TmcCntlCloseGCodeFile = function(mInst:integer):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
Type TmcCntlRewindFile = function(mInst:integer):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
type TmcCntlEStop = function( mInst:integer):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
Type TmcCntlEnable =function( mInst:integer;State:Boolean):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
type TmcCntlReset = function( mInst:integer):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
Type TmcAxisGetPos = function( mInst:integer; axisId:integer; val:pdouble):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
Type TmcAxisSetPos = function( mInst:integer; axisId:integer; val:pdouble):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
Type TmcCntlCycleStart = function(mInst:integer):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
Type TmcCntlCycleStop = function(mInst:integer):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
Type TmcCntlGcodeExecuteWait = function(mInst:integer;commands:pChar):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
Type TmcAxisHome = function( mInst:integer; axisId:integer):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
Type TmcAxisIsHomed = function( mInst:integer;axisId:integer;homed:pBoolean):integer;{$IFDEF WIN32} stdcall; {$ENDIF}
type TMach4Control=class(TObject)
private
fLoaded : Boolean;
fConnected : Boolean;
public
mcIpcInit :TmcIpcInit;
mcGetInstance :TmcGetInstance;
mcIpcCleanup :TmcIpcCleanup;
mcCntlEStop :TmcCntlEStop;
mcCntlEnable :TmcCntlEnable;
mcCntlReset :TmcCntlReset;
mcRegGetValue :TmcRegGetValue;
mcCntlLoadGcodeFile:TmcCntlLoadGcodeFile;
mcCntlCloseGcodeFile:TmcCntlCloseGcodeFile;
mcCntlRewindFile :TmcCntlRewindFile;
mcAxisGetPos :TmcAxisGetPos;
mcAxisSetPos :TmcAxisSetPos;
mcCntlCycleStart :TmcCntlCycleStart;
mcCntlCycleStop :TmcCntlCycleStop;
mcCntlGcodeExecuteWait:TmcCntlGcodeExecuteWait;
mcAxisHome :TmcAxisHome;
mcAxisIsHomed :TmcAxisIsHomed;
Handle :Thandle;
mInst :Integer;
property Loaded :Boolean read fLoaded write fLoaded;
property Connected :Boolean read fConnected write fConnected;
function init(dllLoc:pChar):Boolean;
procedure doConnect(myIP:pChar);
procedure cleanUp;
constructor create;
end;
function ErrGetProcAddress(h:THandle;procName:pAnsiChar):FARPROC;
type handle = Integer;
implementation
function ErrGetProcAddress(h:THandle;procName:pAnsiChar):FARPROC;
begin
result:=getProcAddress(h,procName);
if not assigned(result) then
raise exception.Create('DLL does not contain function: '+ProcName);
// usually a typo in the function name if failed
end;
constructor TMach4Control.create;
begin
inherited;
end;
function TMach4Control.init(dllLoc:pChar):Boolean;
begin
//get the address of each function in the dll
Handle := LoadLibrary(dllLoc);//'c:\Mach4Hobby\mach4IPC.dll');
Loaded:= Handle <> 0 ;
mcIpcInit:=ErrGetProcAddress(handle,'mcIpcInit');
mcIpcCleanup:=ErrGetProcAddress(handle,'mcIpcCleanup');
mcCntlEStop:=ErrGetProcAddress(handle,'mcCntlEStop');
mcCntlEnable:=ErrGetProcAddress(handle,'mcCntlEnable');
mcCntlReset:=ErrGetProcAddress(handle,'mcCntlReset');
mcCntlLoadGcodeFile:=ErrGetProcAddress(handle,'mcCntlLoadGcodeFile');
mcCntlCloseGcodeFile:=ErrGetProcAddress(handle,'mcCntlCloseGCodeFile');
mcCntlRewindFile:=ErrGetProcAddress(handle,'mcCntlRewindFile');
mcAxisGetPos:=ErrGetProcAddress(handle,'mcAxisGetPos');
mcAxisSetPos:=ErrGetProcAddress(handle,'mcAxisSetPos');
mcCntlCycleStart:=ErrGetProcAddress(handle,'mcCntlCycleStart');
mcCntlCycleStop:=ErrGetProcAddress(handle,'mcCntlCycleStop');
mcCntlGcodeExecuteWait:=ErrGetProcAddress(handle,'mcCntlGcodeExecuteWait');
mcAxisHome:=ErrGetProcAddress(handle,'mcAxisHome');
mcAxisIsHomed:=ErrGetProcAddress(handle,'mcAxisIsHomed');
end;
procedure TMach4Control.doConnect(myIP:pChar);
begin
// connect to a running of Mach4
if @mcIpcInit <> nil then
begin
mInst:=mcIpcInit(myIP);
Connected:=(mInst=0);
end;
end;
procedure TMach4Control.cleanUp;
begin
if @mcIpcCleanup <> nil then
mcIpcCleanup;
end;
end.
This code is for the application shown in the jpg
unit frmMach4AccessMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, JvExStdCtrls, JvEdit, JvValidateEdit, Mask,
JvExMask, JvToolEdit, JvExControls, JvSpeedButton, TILed,
MachLed, ExtCtrls, Mach4DllWrapper;
type
TForm1 = class(TForm)
btnLoadFile: TButton;
stat1: TStatusBar;
btnEnable: TButton;
btnCycleStart: TButton;
btnCycleStop: TButton;
btnRewind: TButton;
btnCloseFile: TButton;
btnMDIexecute: TButton;
mmo1: TMemo;
eGCodeFile: TJvFilenameEdit;
pnl1: TPanel;
lbl1: TLabel;
eXdro: TJvValidateEdit;
btnZeroXdro: TJvSpeedButton;
btnXhome: TJvSpeedButton;
MachLedxDro: tMachLed;
MachLed2: tMachLed;
pnl2: TPanel;
lbl3: TLabel;
btnZeroZdro: TJvSpeedButton;
btnZhome: TJvSpeedButton;
MachLedZdro: tMachLed;
MachLed5: tMachLed;
eZdro: TJvValidateEdit;
procedure btnLoadFileClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure btnEnableClick(Sender: TObject);
procedure btnCycleStartClick(Sender: TObject);
procedure btnCycleStopClick(Sender: TObject);
procedure btnCloseFileClick(Sender: TObject);
procedure btnRewindClick(Sender: TObject);
procedure btnMDIexecuteClick(Sender: TObject);
procedure btnZeroXdroClick(Sender: TObject);
procedure btnXhomeClick(Sender: TObject);
procedure btnZhomeClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
myIP: string = '127.0.0.1';
dllLocation: string = 'c:\Mach4Hobby\mach4IPC.dll';
mc:TMach4Control;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
d:Double;
homed:boolean;
begin
mc:=TMach4Control.create;
mc.init(pChar(DllLocation)); //load the dll and find the function locations
if mc.Loaded then
begin
stat1.Panels[0].Text:='Loaded'; //Status: successfully Loaded
btnLoadFile.Enabled:=mc.Loaded; //determine whoter to enable or not
btnEnable.Enabled:=mc.Loaded; //determine whoter to enable or not
end else
begin
stat1.Panels[0].Text:='Load Failure';
exit;
end;
stat1.Panels[1].Text:='Connecting...';
application.ProcessMessages;
if mc=nil then
exit;
if mc.Connected then
exit;
mc.doConnect(pChar(myIP)); //connect to a running Mach4 instance
if mc.Connected then
stat1.Panels[1].Text:='Connected to Mach4'
else
stat1.Panels[1].Text:='Failed to Connect';
application.ProcessMessages;
mc.mcAxisGetPos(mc.mInst,0,@d); //get the Xdro position-need to write a thread to update
eXdro.Value:=d;
mc.mcAxisGetPos(mc.mInst,2,@d); //get the Zdro position-need to write a thread to update
eZdro.Value:=d;
mc.mcAxisIsHomed(mc.mInst,0,@homed);
if homed then
MachLedxDro.Color:=clGreen
else
MachLedxDro.Color:=clMaroon;
mc.mcAxisIsHomed(mc.mInst,2,@homed);
if homed then
MachLedzDro.Color:=clGreen
else
MachLedzDro.Color:=clMaroon;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//clean up before exiting
if mc<>nil then
mc.mcIpcCleanup;
freeLibrary(mc.Handle);
end;
procedure TForm1.btnLoadFileClick(Sender: TObject);
var
i:integer;
s:string;
begin
//load GCodeFile listed in edit control
stat1.Panels[2].Text:='Loading GCode file';
application.ProcessMessages;
s:=eGcodeFile.FileName;
i:=mc.mcCntlLoadGcodeFile(mc.mInst,pChar(eGcodeFile.filename));
stat1.Panels[2].Text:='Return Code: '+intToStr(i);
end;
procedure TForm1.btnEnableClick(Sender: TObject);
begin
//code to enable and disable Mach and update button state
if btnEnable.Caption='&Enable' then
begin
mc.mcCntlEnable(mc.mInst,True);
btnEnable.Caption:='&Disable';
end else
begin
mc.mcCntlEStop(mc.mInst);
btnEnable.Caption:='&Enable';
end;
btnCycleStart.Enabled:=btnEnable.Caption<>'&Enable';
btnCycleStop.Enabled:=btnEnable.Caption<>'&Enable';
end;
procedure TForm1.btnCycleStartClick(Sender: TObject);
begin
mc.mcCntlCycleStart(mc.mInst);
btnCycleStop.SetFocus;
end;
procedure TForm1.btnCycleStopClick(Sender: TObject);
begin
mc.mcCntlCycleStop(mc.mInst);
end;
procedure TForm1.btnCloseFileClick(Sender: TObject);
begin
mc.mcCntlCloseGcodeFile(mc.mInst);
mc.mcCntlRewindFile(mc.mInst);//close file doesnt clear gcode window
end;
procedure TForm1.btnRewindClick(Sender: TObject);
begin
mc.mcCntlRewindFile(mc.mInst);
end;
procedure TForm1.btnMDIexecuteClick(Sender: TObject);
begin
//execute gcode in the momo component
mc.mcCntlGcodeExecuteWait(mc.mInst,pChar(mmo1.Text));
end;
procedure TForm1.btnZeroXdroClick(Sender: TObject);
var
d:double;
begin
d:=0;
mc.mcAxisSetPos(mc.mInst,0,@d);
end;
procedure TForm1.btnXhomeClick(Sender: TObject);
begin
if mc.mcAxisHome(mc.mInst,0)=0 then
MachLedxDro.color:=clGreen;
end;
procedure TForm1.btnZhomeClick(Sender: TObject);
begin
if mc.mcAxisHome(mc.mInst,2)=0 then
MachLedxDro.color:=clGreen;
end;
end.
Hope this saves someone some time.
RT
-
That's great info - thanks!! But... Do you know where one might find C/C++ header files to make the process of wrapping a bit easier than copy/paste/edit from Mach4CoreAPI.chm file (which doesn't seem to even have any references to IPC related methods)...
MM