vmc.dll API
A C-style control interface to the virtual machine, callable from any language.
What it is
vmc.dll (virtual machine control) exposes the virtual machine as a set of C functions. Two uses:
automated testing (run calibration procedures in CI) and teaching (drive devices from a
Python script).
Plain C exports — no C++ name mangling, no COM, no .NET dependency. ctypes, P/Invoke, JNA and
LabVIEW all call it directly.
Lifetime
VMC_HANDLE vmc_open(const char* machineConfigPath); // NULL on failure
void vmc_close(VMC_HANDLE h);
int vmc_last_error(VMC_HANDLE h);
const char* vmc_last_error_message(VMC_HANDLE h);Every function returns 0 on success and a negative error code otherwise.
Axes
int vmc_axis_home(VMC_HANDLE h, const char* axisId);
int vmc_axis_move_abs(VMC_HANDLE h, const char* axisId, double targetMm, int waitMs);
int vmc_axis_move_rel(VMC_HANDLE h, const char* axisId, double deltaMm, int waitMs);
int vmc_axis_position(VMC_HANDLE h, const char* axisId, double* outMm);
int vmc_axis_stop(VMC_HANDLE h, const char* axisId);waitMs = 0 returns immediately; -1 waits for in-position.
Camera
int vmc_cam_grab(VMC_HANDLE h, const char* camId,
unsigned char* buf, int bufSize,
int* outWidth, int* outHeight, int* outStride);
int vmc_cam_set_exposure(VMC_HANDLE h, const char* camId, double us);
int vmc_cam_set_gain(VMC_HANDLE h, const char* camId, double db);Images are 8-bit grey, row-major; stride may exceed width because of alignment.
IO
int vmc_io_read(VMC_HANDLE h, int channel, int* outValue);
int vmc_io_write(VMC_HANDLE h, int channel, int value);Calibration
int vmc_calib_run(VMC_HANDLE h, const char* procedureId,
const char* paramsJson,
char* outJson, int outJsonSize);
int vmc_calib_get(VMC_HANDLE h, const char* procedureId,
char* outJson, int outJsonSize);procedureId is one of C1-pixel-size, C2-hand-eye, C3-intrinsics, C4-galvo-field,
C5-z-focus, C6-stage-geometry.
The returned JSON includes the truth comparison (virtual devices only):
{
"procedure": "C1-pixel-size",
"ok": true,
"solved": { "mmPerPx": 0.019823, "thetaRad": 0.0041, "skew": 1.6e-4 },
"truth": { "mmPerPx": 0.019841, "thetaRad": 0.0039 },
"verify": { "deviationMm": 0.018, "toleranceMm": 0.05, "pass": true },
"residual": { "rmsPx": 0.081, "maxPx": 0.213 }
}Fault injection
The most useful group for testing: break a device deliberately and see whether your software notices.
int vmc_fault_set(VMC_HANDLE h, const char* deviceId, const char* faultJson);
int vmc_fault_clear(VMC_HANDLE h, const char* deviceId);{ "backlashUm": 50, "noiseScale": 4.0, "k1": -0.08, "stuckAt": null }Versioning
int vmc_version(char* outSemver, int size);The interface is versioned: additive within 1.x, breaking changes only on a major release.
Test code should check the major version at start-up.
Threading
A VMC_HANDLE is not thread safe. Use one handle per thread, or your own lock. Multiple virtual
machine instances can run in parallel, so CI can run tests concurrently.