我想为python创建一个c扩展,它具有一个可用的函数,该函数将回调函数作为参数。此c函数将在Windows中设置一个全局钩子,以监视击键,而Keyboardhookproc将调用python函数以在按下键时进行处理。
仅当执行PyObject_CallObject行与该方法结束之间存在消息框功能时,回调函数才起作用。我一直在使用消息框查看代码在做什么,因为我没有命令行。 python程序以没有消息框功能的退出代码-1073741819结尾。为什么会这样呢?同样,键盘挂钩也无法正常工作,我不确定是否需要消息循环,这只是我尝试过的另一件事。
//the c extension
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <windows.h>
#include <io.h>
PyObject* call(char theKey);
static PyObject* setHook(PyObject* dummy, PyObject *args);
static PyObject* callback = NULL;
static PyObject* SpamError;
HHOOK keyboardHook;
static PyMethodDef callPythonMethods[] = {
{"setHook", setHook, METH_VARARGS,
"Set the hook and callback method"},
{NULL, NULL, 0, NULL} /* Sentinel */
};
static struct PyModuleDef callPythonModule = {
PyModuleDef_HEAD_INIT,
"CallPython",
NULL,
-1,
callPythonMethods
};
PyMODINIT_FUNC
PyInit_CallPython(void)
{
PyObject* m;
m = PyModule_Create(&callPythonModule);
if (m == NULL)
return NULL;
SpamError = PyErr_NewException("spam.error", NULL, NULL);
Py_INCREF(SpamError);
PyModule_AddObject(m, "error", SpamError);
return m;
}
int
main(int argc, char* argv[])
{
wchar_t* program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
/* Add a built-in module, before Py_Initialize */
PyImport_AppendInittab("CallPython", PyInit_CallPython);
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(program);
/* Initialize the Python interpreter. Required. */
Py_Initialize();
/* Optionally import the module; alternatively,
import can be deferred until the embedded script
imports it. */
PyImport_ImportModule("CallPython");
PyMem_RawFree(program);
return 0;
}
LRESULT CALLBACK keyBoardHookProc(
_In_ int code,
_In_ WPARAM wParam,
_In_ LPARAM lParam)
{
MessageBox(NULL, "well it worked", "Logging", MB_OK);
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
char* test = "it worked";
// If key is being pressed
if (wParam == WM_KEYDOWN) {
switch (p->vkCode) {
// Invisible Keys
default:
//call((char*)tolower(p->vkCode));
call(test);
}
}
return CallNextHookEx(keyboardHook, code, wParam, lParam);
}
static PyObject* setHook(PyObject* dummy, PyObject* args) {
PyObject* result = NULL;
PyObject* temp;
if (PyArg_ParseTuple(args, "O:set_callback", &temp)) {
if (!PyCallable_Check(temp)) {
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
return NULL;
}
Py_XINCREF(temp);
Py_XDECREF(callback);
callback = temp;
Py_INCREF(Py_None);
result = Py_None;
}
keyboardHook = SetWindowsHookEx(
WH_KEYBOARD_LL,
keyBoardHookProc,
NULL,
0
);
MessageBox(NULL, "we loggin boyz", "Logging", MB_OK);
char* fine = "i";
call(fine);
MessageBox(NULL, "called fine", "Logging", MB_OK);
MSG msg;
while (!GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
MessageBox(NULL, "got and dispatched messages", "Logging", MB_OK);
}
return result;
}
PyObject* call(char* theKey)
{
PyObject* arglist;
PyObject* result;
arglist = Py_BuildValue("(s)", theKey);
result = PyObject_CallObject(callback, arglist);
Py_DECREF(arglist);
if (result == NULL) {
MessageBox(NULL, "result is null :/", "Logging", MB_OK);
return NULL;
}
Py_DECREF(result);
}
//the python script
from CallPython import setHook
import threading
def call_from_C(theKey):
print("oy ello there mate " + theKey)
def startHook():
setHook((call_from_C))
while True:
None
print("creating thread")
thread = threading.Thread(target=startHook, args=())
print("starting thread...")
thread.start()
print("started the logging thread")
print("hmm")
while True:
None
通话(精细);无论是否带有messagebox函数,都应该在python中正确调用回调函数。消息循环是否必要?另外,如果需要循环,是否需要在另一个线程上运行该循环,以便从python调用的函数返回到python?