Я хочу создать расширение ac для python, в котором есть одна функция, доступная для python, которая принимает функцию обратного вызова в качестве параметра.Эта функция c установит глобальный хук в окнах для отслеживания нажатий клавиш, а клавиатурный крючок вызовет функцию 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
call (отлично);должен вызывать функцию обратного вызова в Python правильно с или без функции messagebox.Нужен ли цикл сообщений?Кроме того, если требуется цикл, должен ли этот цикл выполняться в другом потоке, чтобы функция, вызываемая из python, возвращалась обратно в python?