将 python 函数作为回调传递给 C 库

问题描述 投票:0回答:0

我有 C DLL 库,我尝试向它添加 python 接口。这是头文件:

typedef struct
{
    unsigned int keyIdx         : 8;        // index of the G key or mouse button, for example, 6 for G6 or Button 6
    unsigned int keyDown        : 1;        // key up or down, 1 is down, 0 is up
    unsigned int mState         : 2;        // mState (1, 2 or 3 for M1, M2 and M3)
    unsigned int mouse          : 1;        // indicate if the Event comes from a mouse, 1 is yes, 0 is no.
    unsigned int reserved1      : 4;        // reserved1
    unsigned int reserved2      : 16;       // reserved2
} GkeyCode;

// Callback used to allow client to react to the Gkey events. It is called in the context of another thread.
typedef void (__cdecl *logiGkeyCB)(GkeyCode gkeyCode, const wchar_t* gkeyOrButtonString, void* context);

typedef struct
{
    logiGkeyCB gkeyCallBack;
    void* gkeyContext;
} logiGkeyCBContext;

// Enable the Gkey SDK by calling this function
BOOL LogiGkeyInit(logiGkeyCBContext* gkeyCBContext);

// Enable the Gkey SDK by calling this function if not using callback. Use this initialization if using Unreal Engine
BOOL LogiGkeyInitWithoutCallback();

//Enable the Gkey SDK be calling this function if not using context. Use this initialization if working with Unity Engine
BOOL LogiGkeyInitWithoutContext(logiGkeyCB gkeyCallBack);

// Check if a mouse button is currently pressed
BOOL LogiGkeyIsMouseButtonPressed(const int buttonNumber);

// Get friendly name for mouse button
wchar_t* LogiGkeyGetMouseButtonString(const int buttonNumber);

// Check if a keyboard G-key is currently pressed
BOOL LogiGkeyIsKeyboardGkeyPressed(const int gkeyNumber,const  int modeNumber);

// Get friendly name for G-key
wchar_t* LogiGkeyGetKeyboardGkeyString(const int gkeyNumber,const  int modeNumber);

// Disable the Gkey SDK, free up all the resources.
void LogiGkeyShutdown();

我尝试这样的事情:

import ctypes
import time

# Define the GkeyCode structure
class GkeyCode(ctypes.Structure):
    _fields_ = [
        ("keyIdx", ctypes.c_uint, 8),
        ("keyDown", ctypes.c_uint, 1),
        ("mState", ctypes.c_uint, 2),
        ("mouse", ctypes.c_uint, 1),
        ("reserved1", ctypes.c_uint, 4),
        ("reserved2", ctypes.c_uint, 16)
    ]

# Define the logiGkeyCBContext structure
class logiGkeyCBContext(ctypes.Structure):
    _fields_ = [
        ("gkeyCallBack", ctypes.CFUNCTYPE(None, GkeyCode, ctypes.c_wchar_p, ctypes.c_void_p)),
        ("gkeyContext", ctypes.c_void_p)
    ]

# Load the Logitech Gaming G-key SDK dynamic library
dll_path = "C:\\Program Files\\Logitech Gaming Software\\GkeySDK_8.57.148\\Lib\\GameEnginesWrapper\\x64\\LogitechGkeyEnginesWrapper.dll"
gkey_lib = ctypes.CDLL(dll_path)

# Define the callback function
def gkey_callback(gkeyCode, gkeyOrButtonString, context):
    print(f"Received G-key or button event: keyIdx={gkeyCode.keyIdx}, keyDown={gkeyCode.keyDown}, mState={gkeyCode.mState}, mouse={gkeyCode.mouse}")
    print(f"G-key or button string: {gkeyOrButtonString}")
    print(f"Context: {context}")

# Create an instance of the logiGkeyCBContext structure
context = logiGkeyCBContext()
callback_func_type = ctypes.CFUNCTYPE(None, GkeyCode, ctypes.c_wchar_p, ctypes.c_void_p)
callback_func = callback_func_type(gkey_callback)
context.gkeyCallBack = callback_func
context.gkeyContext = ctypes.c_void_p(0)  # Set the context to whatever is appropriate

# Call the Logitech Gaming G-key SDK function that accepts the logiGkeyCBContext structure
gkey_lib.LogiGkeyInit.restype = ctypes.c_bool
gkey_lib.LogiGkeyInit.argtypes = (ctypes.POINTER(logiGkeyCBContext),)

success = gkey_lib.LogiGkeyInit(ctypes.byref(context))
if success:
    print("Logitech Gaming G-key SDK initialized successfully.")
else:
    print("Failed to initialize Logitech Gaming G-key SDK.")

c = 0
while c < 100:
    c += 1
    time.sleep(0.1)

# When done, shutdown the G-key SDK
gkey_lib.LogiGkeyShutdown()

运行,初始化成功,但随后我尝试按下任何 G 键,但从未执行回调? 以上是我的代码。

LogitechGkeyEnginesWrapper.dll
库是罗技 G-Key SDK 的一部分,可在此处获取参考:https://www.logitechg.com/sdk/GkeySDK_8.57.148.zip

SDK中有C++的例子


// DisplayGkeysDlg.cpp : implementation file
//

#include "stdafx.h"
#include "DisplayGkeys.h"
#include "DisplayGkeysDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define CALLBACKMSG (WM_USER + 1)
HWND g_hwnd = NULL;

//Comment this to enable the polling method and disable the callback
#define USE_CALLBACK


#include "LogitechGkeyLib.h"
#pragma comment(lib, "LogitechGkeyLib.lib")

void __cdecl GkeySDKCallback(GkeyCode gkeyCode, wchar_t* gkeyOrButtonString, void* /*pContext*/)
{
    SendMessage(g_hwnd, CALLBACKMSG, (WPARAM)&gkeyCode, (LPARAM)gkeyOrButtonString);
}

// CAboutDlg dialog used for App About

class CAboutDlg : public CDialogEx
{
public:
    CAboutDlg();

// Dialog Data
    enum { IDD = IDD_ABOUTBOX };

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CDisplayGkeysDlg dialog




CDisplayGkeysDlg::CDisplayGkeysDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(CDisplayGkeysDlg::IDD, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CDisplayGkeysDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_LIST_GKEYS, m_listGkeys);
}

BEGIN_MESSAGE_MAP(CDisplayGkeysDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_TIMER()
    ON_WM_CLOSE()
END_MESSAGE_MAP()


// CDisplayGkeysDlg message handlers

BOOL CDisplayGkeysDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    g_hwnd = m_hWnd;

    // Add "About..." menu item to system menu.

    // IDM_ABOUTBOX must be in the system command range.
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);         // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon

    SetTimer(1, 30,NULL);

    logiGkeyCBContext gkeyContext;
    ZeroMemory(&gkeyContext, sizeof(gkeyContext));
    gkeyContext.gkeyCallBack = (logiGkeyCB)GkeySDKCallback;
    gkeyContext.gkeyContext = NULL;


#ifdef USE_CALLBACK
    LogiGkeyInit(&gkeyContext);
#else
    LogiGkeyInit(NULL);
#endif // USE_CALLBACK

    return TRUE;  // return TRUE  unless you set the focus to a control
}

void CDisplayGkeysDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CDisplayGkeysDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CDisplayGkeysDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}

void CDisplayGkeysDlg::OnTimer(UINT_PTR nIDEvent)
{

for (int index = 6; index <= LOGITECH_MAX_MOUSE_BUTTONS; index++)
    {
    if (LogiGkeyIsMouseButtonPressed(index))
    {
        m_listGkeys.InsertString(m_listGkeys.GetCount(), LogiGkeyGetMouseButtonString(index));
        m_listGkeys.SetCaretIndex(m_listGkeys.GetCount() - 1);
    }
}

for (int index = 1; index <= LOGITECH_MAX_GKEYS; index++)
{
    for (int mKeyIndex = 1; mKeyIndex <= LOGITECH_MAX_M_STATES; mKeyIndex++)
    {
        if (LogiGkeyIsKeyboardGkeyPressed(index, mKeyIndex))
        {
            m_listGkeys.InsertString(m_listGkeys.GetCount(), LogiGkeyGetKeyboardGkeyString(index, mKeyIndex));
            m_listGkeys.SetCaretIndex(m_listGkeys.GetCount() - 1);
        }
    }
}

    CDialogEx::OnTimer(nIDEvent);
}


void CDisplayGkeysDlg::OnClose()
{
    LogiGkeyShutdown();
    CDialogEx::OnClose();
}


BOOL CDisplayGkeysDlg::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    // TODO: Add your specialized code here and/or call the base class

    if (message == CALLBACKMSG)
    {
        GkeyCode* gkeyCode = (GkeyCode*)wParam;
        //wchar_t* text = (wchar_t*)lParam; // Can use text from callback, or use SDK function
        wchar_t* text = NULL;

        if (gkeyCode->mouse)
        {
            text = LogiGkeyGetMouseButtonString(gkeyCode->keyIdx);
            lstrcatW(text, (1 == gkeyCode->keyDown) ? L" down" : L" up");
            m_listGkeys.InsertString(m_listGkeys.GetCount(), text);
            m_listGkeys.SetCaretIndex(m_listGkeys.GetCount() - 1);
        }
        else
        {
            text = LogiGkeyGetKeyboardGkeyString(gkeyCode->keyIdx, gkeyCode->mState);
            lstrcatW(text, (1 == gkeyCode->keyDown) ? L" down" : L" up");
            m_listGkeys.InsertString(m_listGkeys.GetCount(), text);
            m_listGkeys.SetCaretIndex(m_listGkeys.GetCount() - 1);
        }
    }

    return CDialogEx::OnWndMsg(message, wParam, lParam, pResult);
}

任何人都知道哪里出了问题,或将我推向正确的方向?

python c dll ctypes
© www.soinside.com 2019 - 2024. All rights reserved.