I found the place in the code to try to understand what is happening, but am a little out of my depth In libffi_support.m
case _C_ID: if (argtype[1] == '?') { /* Argument is a block */ if (argument == Py_None) { argbuf_cur = align(argbuf_cur, PyObjCRT_AlignOfType(argtype)); arg = argbuf + argbuf_cur; argbuf_cur += PyObjCRT_SizeOfType(argtype); PyObjC_Assert(argbuf_cur <= argbuf_len, -1); *(void**)arg = NULL; } else { if (methinfo->argtype[i]->callable == NULL) { PyErr_Format(PyExc_TypeError, "Argument %" PY_FORMAT_SIZE_T "d is a block, but no signature available", i); return -1; } argbuf_cur = align(argbuf_cur, PyObjCRT_AlignOfType(argtype)); arg = argbuf + argbuf_cur; argbuf_cur += PyObjCRT_SizeOfType(argtype); PyObjC_Assert(argbuf_cur <= argbuf_len, -1); *(void**)arg = PyObjCBlock_Create(methinfo->argtype[i]->callable, argument); if (*(void**)arg == NULL) { return -1; } byref_attr[i].buffer = PyCapsule_New( *(void**)arg, "objc.__block__", block_capsule_cleanup); } arglist[i] = signature_to_ffi_type(argtype); values[i] = arg; break; } Is this telling me that I am not passing a python callable? > On Jan 6, 2020, at 09:27, Ronald Oussoren <ronaldousso...@mac.com> wrote: > > > >> On 6 Jan 2020, at 00:51, Rand Dvorak <randdvo...@gmail.com> wrote: >> >> >> I am trying to implement a simple server in PyObjC for the Criollo HTTP >> server. The server has a method to set route handlers by passing a block to >> setup the route and then when it receives and HTTP request for the route it >> calls the block. The block has the signature: >> >> typedef void(^CRRouteBlock)(CRRequest* _Nonnull request, CRResponse* >> _Nonnull response, CRRouteCompletionBlock _Nonnull completionHandler); >> >> >> So, here is my simple proof of concept: >> >> import objc >> CRApplication = objc.lookUpClass("CRApplication") >> global server >> >> def helloHandler(self, request, response, handler): >> response.send_("Hello World!") >> handler() >> >> if __name__ == "__main__": >> server = CRApplication.sharedApplication().delegate().server() >> server.get_block_("/", objc.selector(helloHandler, >> signature=b'v@:@@@‘)) *** error occurs here >> server.startListening() >> >> >> But, when I try to setup the route I get the following error: >> >> Traceback (most recent call last): >> File "main.py", line 21, in <module> >> server.get_block_("/", objc.selector(helloHandler, signature=b'v@:@@')) >> TypeError: Argument 3 is a block, but no signature available >> >> >> Any ideas how to workaround this issue and implement the route handlers in >> PyObjC? > > The code below should do the trick, but eas typed directly into this mail and > might therefore contain syntax errors. > > import objc > objc.registerMetaDataForSelector( > b”CRApplication”, # name of the class implementing “get_block:”, or > “NSObject” > b”get_block:”, > { > “arguments”: { > 2: { > “callable”: { > “arguments”: { > 0: { “type”: b”^v” }, > 1: { “type”: b”@” }, > 2: { “type”: b”@” }, > 3: { “type”: b”@” } > }, > “retail”: { “type”: b”v” } > } > } > } > ) > > This tells the bridge the signature for the block argument of the > “get_block:” selector, which is information that cannot be retrieved from the > Objective-C runtime. Argument 2 is the first real argument of ObjC > selectors, after the implicit arguments “self” and “_imp” (which is not > available in python code). > > Ronald > — > > Twitter: @ronaldoussoren > Blog: https://blog.ronaldoussoren.net/ >> _______________________________________________ >> Pythonmac-SIG maillist - Pythonmac-SIG@python.org >> https://mail.python.org/mailman/listinfo/pythonmac-sig >> unsubscribe: https://mail.python.org/mailman/options/Pythonmac-SIG >
_______________________________________________ Pythonmac-SIG maillist - Pythonmac-SIG@python.org https://mail.python.org/mailman/listinfo/pythonmac-sig unsubscribe: https://mail.python.org/mailman/options/Pythonmac-SIG