I’ve got libmodbus working in my Xojo project to talk to an external Motion control unit over ModbusTCP. I am testing this now using a Windows-based Modbus slave simulator and so far so good. The one thing I can’t quite wrap my head around is how to catch any errors that libmodbus generates.
Most of the functions I’m using return an integer value, to indicate success or failure. if there’s a failure, you can get the text of the error using the errno variable. Libmodbus includes the standard C errno.h header, so if I have the errno variable, I can pass that to another libmodbus function to retrieve the actual error text.
Maybe this is a dumb question, but how do I access errno from within Xojo in order to call the libmodbus modbus_strerror() function?
Unless I’m not reading that correctly, this code is letting me look up the text of an error using a known error number, correct?
The problem is that I don’t know the errno that limbodbus is generating when one of its functions returns a failure.
The list of functions in libmodbus is not especially long, but I can’t find one that fetches the last error. I think the assumption is that if you’re using the library you’re coding in C and maybe then you have access to errno, which appears to be a global variable in C. but because I’m calling discrete functions from the library as needed, from Xojo, wouldn’t I need an explicit function in libmodbus to fetch the most recent error? Or maybe I’m just completely misunderstanding how this works.
Actually - do you know what the equivalent lib would be on Mac? I’m testing on mac, but running my modbus simulator on a Windows machine on the network.
I have this method for Windows/Linux/Mac, but I’ve only ever tested the Windows and Linux sides:
Function get_errno() As Integer
Dim err As Integer
Dim mb As MemoryBlock
#If TargetWin32 Then
Declare Function _get_errno Lib "msvcrt" (ByRef Error As Integer) As Integer
Dim e As Integer = _get_errno(err)
If e <> 0 Then err = e
#elseif TargetLinux
Declare Function __errno_location Lib "libc.so" () As Ptr
mb = __errno_location()
#elseif TargetMacOS
Declare Function __error Lib "System" () As Ptr
mb = __error()
#endif
If mb <> Nil Then err = mb.Int32Value(0)
Return err
End Function
As the underlying int errno should follow the OS bitness, the code should not follow it? Something as
Dim err As Integer
Dim mb As MemoryBlock
#If TargetWindows Then
Declare Function _get_errno Lib "msvcrt" (ByRef Error As Integer) As Integer
Dim e As Integer = _get_errno(err)
If e <> 0 Then err = e
#elseif TargetLinux
Declare Function __errno_location Lib "libc.so" () As Ptr
mb = __errno_location()
#elseif TargetMacOS
Declare Function __error Lib "System" () As Ptr
mb = __error()
#endif
#if Target64Bit Then
If mb <> Nil Then err = mb.Int64Value(0)
#else
If mb <> Nil Then err = mb.Int32Value(0)
#EndIf
Return err