You tried to simply cast the value returned by Snap()
into a Cvb.Error.CVC_ERROR_CODES
enum. That won’t work. Well, technically speaking it works, but it doesn’t yield anything useful. Functions in the C-API of return either a bool
value or a HRESULT
-like value (there are very few - and unfortunate - exceptions to that rule). The HRESULT
convention dictates that the uppermost bit of the return value is to be set if an error occurred (making the error check fairly easy: Anything less than zero is an error, zero or positive values aren’t). Values like -2147483644 (= 0x8000 0004) are, however, quite the piece of work to write into an enumeration. Add to that the fact that e.g. the old Borland C++ compilers did by default treat enums are 8-bit variables and you have the mess that prompted the pattern that is being used: Any function returning an error will internally always use the CVC_ERROR
macro from CVCError.h to generate its return values…
… and anyone wanting to evaluate the return value in terms of the CVC_ERROR_CODES
will need to apply the inverse operation CVC_ERROR_FROM_HRES
(all these two macros ever really do is set and unset the uppermost bit in the integer). When the original C# wrappers were written this pattern was simply transcribed to C#. C# has the added benefit of being able to directly convert the enum values to strings (you got that part right, however your integer value could not by mapped to one of the enum values and was therefore just output as a number), so in order to improve the output I’d recommend something like this:
Cvb.Error.CVC_ERROR_CODES errorCode = (Cvb.Error.CVC_ERROR_CODES)Cvb.Error.CVC_ERROR_FROM_HRES(Cvb.Driver.IGrabber.Snap(_hImg));
… and as you asked for suggestions to improve the code:
- use
var
where possible - especially if the name of the type involved is poorly readable
- I’m not a fan of Yoda conditions (https://blog.codinghorror.com/new-programming-jargon/, https://en.wikipedia.org/wiki/Yoda_conditions) as they are counter-intuitive when read (and readability greatly contributes to maintainability), but that is probably just a matter of preference
- in line 12 you overwrite the text you did potentially just set - probably not intended that way
- I’d recommend to stick with one naming convention for variable names; you used lower camel case for most of them, but camel case for
TestText
using Cvb;
...
var errorCode = (Cvb.Error.CVC_ERROR_CODES)Error.CVC_ERROR_FROM_HRES(Driver.IGrabber.Snap(_hImg));
if (errorCode == Error.CVC_ERROR_CODES.CVC_E_OK)
{
Image = _hImg;
// Save Images
var imageName = string.Format("{0}{1}_Camera{2}_{3}.bmp", Settings.FilePath, Settings.FileName, _cameraPort, fileNamePostfix);
if (!Cvb.Image.WriteImageFile(_hImg, imageName))
testText = "Failed to save image: " + imageName;
else
testText = "Done";
}
else
{
testText = "Error snapping image: " + errorCode.ToString();
}
That is about as readable as it gets with the C API. With Cvb.Net your code would roughly look like this:
var status = WaitStatus.Ok;
var snappedImage = myDriver.GetSnapshot(myTimeout, out status);
if (snappedImage != null)
{
var imageName = string.Format("{0}{1}_Camera{2}_{3}.bmp", Settings.FilePath, Settings.FileName, _cameraPort, fileNamePostfix);
try
{
snappedImage.Save(imageName);
testText = "Done";
}
catch(Exception ex)
{
testText = string.Format("Failed to save image {0}: {1}", imageName, ex.Message);
}
}
else
testText = status.ToString();
Fairly similar. Slightly more pleasant to read, mostly due to the lack of all-caps names