I am just new in Python. I am trying to connect to a laser sensor through its DLL library. The SDK functions in this Library are compiled in C++ language.
By using ctypes in python my first try is to call the EthernetScanner_Connect function. The function parameters are as follow:
void* EthernetScanner_Connect(char *chIP, char *chPort, int iTimeOut)
According to the function discription in c++ it should return NULL pointer if a failure in connection occurs, otherwise it should return the handle to the profile sensor, which is gonna be used in other functions.
My code on python untill now:
from ctypes import *
lib=windll.LoadLibrary("c:\\EthernetScanner.dll")
if lib:
print("the Library is loaded")
EthernetScanner_Connect = getattr(lib,"EthernetScanner_Connect")
EthernetScanner_Connect.restype = c_void_p
EthernetScanner_Connect.argtypes =[c_char_p,c_char_p,c_int]
x = EthernetScanner_Connect(b"193.164.200.1\0",b"32407\0",0)
print(x)
while I am expecting NULL from this function because i am not connected to the sensor yet, it is giving me the following:
the Library is loaded
45940800
解决方案
I'm going to post an answer based on some assumptions:
The sensor you're talking about is the same one as described in [FoxControls]: acuity-ap820-users-manual.pdf. If this isn't true, the answer is useless
According to above doc, EthernetScanner_GetConnectStatus's possible return statuses are (emphasis is mine):
Status is a unsigned integer used as a buffer to contain the status code when the
function returns.
The status codes are:
0: Disconnected
1: Disconnecting
2: Connecting
3: Connected
Based on the above, and the fact that the connect timeout is 0, I assumed (nothing in the doc to support it, though) that it tries to connect in non blocking mode:
EthernetScanner_Connect returns immediately (meaning that before attempting to connect - it "schedules" a connection operation if you will) a non NULL pointer. For a non blocking (async) IO example, check [MS.Docs]: connect function
The (above) pointer should be queried (periodically) using EthernetScanner_GetConnectStatus. That's why it makes sense for the pointer to be non NULL (as when EthernetScanner_Connect returns, the connection attempt result is not yet known)
Here's a piece of code that is supposed to deal with the problem (needless to say that it's blind coding - meaning that I didn't actually test it).
As a consequence of the 2nd assumption, if passing a timeout greater than 0, EthernetScanner_Connect should return NULL.
code.py:
#!/usr/bin/env python3
import sys
import ctypes
import time
DLL_NAME = "c:\\EthernetScanner.dll"
CONNECT_STATUS_DISCONNECTED = 0
CONNECT_STATUS_DISCONNECTING = 1
CONNECT_STATUS_CONNECTING = 2
CONNECT_STATUS_CONNECTED = 3
CONNECT_STATUSES_PENDING = [
CONNECT_STATUS_CONNECTING,
CONNECT_STATUS_DISCONNECTING,
]
def main():
connect_timeout_msec = 0
nb_mode = connect_timeout_msec == 0
dll = ctypes.WinDLL(DLL_NAME)
EthernetScanner_Connect = dll.EthernetScanner_Connect
EthernetScanner_Connect.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_uint32]
EthernetScanner_Connect.restype = ctypes.c_void_p
EthernetScanner_GetConnectStatus = dll.EthernetScanner_GetConnectStatus
EthernetScanner_GetConnectStatus.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_uint32)]
EthernetScanner_Disconnect = dll.EthernetScanner_Disconnect
EthernetScanner_Disconnect.argtypes = [ctypes.c_void_p]
EthernetScanner_Disconnect.restype = ctypes.c_uint32
ptr = EthernetScanner_Connect(b"192.168.100.1", b"32001", connect_timeout_msec)
if nb_mode:
print("Non blocking mode: EthernetScanner_Connect returned {:}".format(ptr))
poll_timeout_sec = 0.5
connect_status = ctypes.c_int(CONNECT_STATUS_CONNECTING)
while connect_status.value in CONNECT_STATUSES_PENDING:
time.sleep(poll_timeout_sec)
EthernetScanner_GetConnectStatus(ptr, ctypes.byref(connect_status))
if connect_status.value != CONNECT_STATUS_CONNECTED:
print("Couldn't connect (status: {:})!".format(connect_status.value))
return
else:
print("Blocking mode: EthernetScanner_Connect returned {:}".format(ptr))
if not ptr:
print("Couldn't connect!")
return
# Do something with the sensor (pointer)
EthernetScanner_Disconnect(ptr)
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
print("Done.")