The pycanon package does not work with Canon's current ED SDK, therefore I have started from scratch making a new one. Progress comes step by step, but now I am stuck on catching the camera's events, which invoke a callback mechanism. There are at least two issues with it, and they may well be interrelated.
To start, here is the callback function that I am having called:
def propertyChanged(*args):
print(args)
return window.propertyChanged(*args)
In the header file, this is defined as:
#if defined( BUILD_EDSDK_DLL )
#define EDSAPI EDSEXPORT EDSSTDCALL
#else
#define EDSAPI EDSIMPORT EDSSTDCALL
#endif
/*-----------------------------------------------------------------------------
//
// Function: EdsSetPropertyEventHandler
//
// Description:
// Registers a callback function for receiving status
// change notification events for property states on a camera.
//
// Parameters:
// In: inCameraRef - Designate the camera object.
// inEvent - Designate one or all events to be supplemented.
// inPropertyEventHandler - Designate the pointer to the callback
// function for receiving property-related camera events.
// inContext - Designate application information to be passed by
// means of the callback function. Any data needed for
// your application can be passed.
// Out: None
//
// Returns: Any of the sdk errors.
-----------------------------------------------------------------------------*/
EdsError EDSAPI EdsSetPropertyEventHandler(
EdsCameraRef inCameraRef,
EdsPropertyEvent inEvnet,
EdsPropertyEventHandler inPropertyEventHandler,
EdsVoid* inContext );
It works, more or less, in that it is called with (sometimes) proper arguments. What's wrong is that when I am not in the debugger, the arguments seem to be offsetted by two longInts.
Look at the full test program listed below, especially the run()-method.
What I would expect is that camera.setAEMode(5)
would trigger the callback. It doesn't, but camera.getBodyID()
two lines above it does so, whereas I would not expect this. I suppose that is only my understanding of the working of the API and not the issue I am having.
When the camera.getBodyID()
is being executed (with testCallback
True) and a breakpoint in propertyChanged, I see i is called with the arguments (257, 3, 0, 129568680), which make sense:
However, when running exactly the same while not debugging, the parameters passed to propertyChanged are (107020331, 106511131, 257, 3).
And there is this second issue: when I don't assign the callback function, the program runs just fine. But when I assign True to testCallback
, then the program crashes after returning from the callback (exception: access violation reading 0x0000002B when not debugging, or PROPERTIES_UNAVAILABLE in response to getBodyID()). When the program is run without triggering the callback function (# camera.getBodyID()
), but still with assigning it, then python.exe crashes after leaving the run() -method and thinks it is a good idea telling Microsoft about that.
What should I do to make this work?
from PyQt5.Qt import * # @UnusedWildImport
from canonSDK import edSDK
from canonSDK.edSDK import EDSDK
import traceback
from canonSDK.EDSDKtypes import * # @UnusedWildImport
from ctypes import py_object
# copy of self of the main-window object;
# necessary since it is exceedingly hard to pass self thru the callback
window = None
def propertyChanged(*args):
print(args)
return window.propertyChanged(*args)
class RCmain(QWidget):
def __init__(self):
super().__init__()
global window
window = self
QVBoxLayout(self)
self.console = QTextBrowser()
self.layout().addWidget(self.console)
pnl = QFrame(); self.layout().addWidget(pnl)
pnl.setFixedHeight(30)
btn = QPushButton("run", parent = pnl)
btn.clicked.connect(self.run)
sys.excepthook = self.exceptionHook
def show(self):
super().show()
# initialize dll connection:
self.edsdk = EDSDK()
self.edsdk.initializeSDK()
self.camera = None
# show success by listing the connected cameras:
l = self.edsdk.getCameraList()
n = self.edsdk.getChildCount(l)
self.print(n, "cameras:")
for c in self.edsdk.cameras:
self.print(c.index, ":", c.name)
def close(self):
self.edsdk.terminateSDK()
if self.camera is not None:
self.camera.close()
super().close()
def exceptionHook(self, type, value, tback):
traceback.print_exception(type, value, tback)
def print(self, *args):
print(*args)
self.console.append(" ".join([str(a) for a in args]))
#WINFUNCTYPE (EdsError, EdsPropertyEvent, EdsPropertyID, EdsUInt32, EdsVoid)
def propertyChanged(self, inEvent, inPropertyID, inParam, inContext):
self.print(inEvent, inPropertyID, inParam, inContext)
self.print(EdsPropID(inPropertyID).name, "has changed") # EdsPropID is an IntEnum
return 0
def run(self):
# test sequence
camera = self.edsdk.getCamera(0)
testCallback = True
if testCallback:
self.edsdk.setPropertyEventHandler(camera.reference,
EdsPropertyEvents.All,
EdsPropertyEventHandler(propertyChanged))
self.print(camera.getProductName())
self.print(camera.getBodyID())
self.print(camera.getAEMode())
camera.setAEMode(5)
self.print(camera.getAEMode())
camera.startLiveView()
# camera.downloadEvfData() # 2b impl'd
camera.endLiveView()
self.camera = camera
if __name__ == '__main__':
import sys
edSDK.setDllPath('D:/python3/remote shooting/EDSDKv2.7/EDSDK/Dll')
app = QApplication(sys.argv)
w = RCmain()
w.show()
app.exec_()
User contributions licensed under CC BY-SA 3.0