Python Load Windows библиотека преобразования C # - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть приложение на C #, которое вызывает Windows DLL (fbwflib.dll).Из этой dll вызывается функция (FbwfIsFilterEnabled), для которой требуется два параметра, переданных по ссылке.

В C # мой код:

public class FBWF_Utilities
{
    [DllImport("fbwflib.dll", SetLastError = true)]
    static extern UIntPtr FbwfIsFilterEnabled(
       [MarshalAs(UnmanagedType.U1)]
       ref bool currentSession,
       [MarshalAs(UnmanagedType.U1)]
       ref bool nextSession
    );
    [DllImport("fbwflib.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.U4)]
    static extern uint FbwfEnableFilter();

    [DllImport("fbwflib.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.U4)]
    static extern uint FbwfDisableFilter();


    public static bool IsEnabledCurrent()
    {
        bool xCurrent = false;
        bool xNext = false;

        if (IsInstalled())
        {
            try
            {
                FbwfIsFilterEnabled(ref xCurrent, ref xNext);
            }
        catch (Exception ex)
            {
                MessageBox.Show("FBWF IsEnabledCurrent exception:\n\n" + ex.Message);
                return false;
            }
        }

        return xCurrent;
    }

Теперь мне нужно преобразовать этот код в код Python.

Я попытался:

@staticmethod
def IsEnabled():
    dllObject = ctypes.cdll.LoadLibrary(r'C:\Windows\System32\fbwflib.dll')
    dllObject.FbwfIsFilterEnabled.argtypes = [ctypes.c_int, ctypes.c_int]
    dllObject.FbwfIsFilterEnabled.restype = None

    current = ctypes.c_int(0)
    next = ctypes.c_int(0)

    dllObject.FbwfIsFilterEnabled(ctypes.byref(current, 0), ctypes.byref(next, 0))
    messagebox.showinfo("", "Current: " + current + "\n" + "Next: " + next)

, но у меня есть ошибка: ctypes.ArgumentError: аргумент 1:: неправильный тип

Я пробовал другие параметризации, но безрезультатнорезультат.

Как правильно загрузить библиотеку с параметрами по ссылке?

Другие функции без параметров работают хорошо:

@staticmethod
def EnableFilter():
    dllObject = ctypes.cdll.LoadLibrary(r'C:\Windows\System32\fbwflib.dll')
    dllObject.FbwfEnableFilter()

@staticmethod
def DisableFilter():
    dllObject = ctypes.cdll.LoadLibrary(r'C:\Windows\System32\fbwflib.dll')
    dllObject.FbwfDisableFilter()

, которые работают без ошибок.

Небольшое описание функции, которая доставляет мне некоторые проблемы, находится здесь: https://www.pinvoke.net/default.aspx/fbwflib.FbwfIsFilterEnabled

РЕДАКТИРОВАТЬ:

меняется с помощью ctypes.pointer asпредложил от Луки (спасибо), теперь у меня была другая ошибка:

Процедура вызвана с недостаточным количеством аргументов (8 байт отсутствует) или неверное соглашение о вызовах

ссылается на строку:

dllObject.FbwfIsFilterEnabled(ctypes.byref(current, 0), ctypes.byref(next, 0))

изменяя строку следующим образом:

dllObject.FbwfIsFilterEnabled(ctypes.POINTER(current), ctypes.POINTER(next))

I rВыявите ошибку: Ошибка типа: должен быть тип ctypes

, который позволяет мне знать, что вызов byref был правильным способом.

изменение, учитывая тип bool, как было сделано в моем коде c #:

@staticmethod
def IsEnabled():
    dllObject = ctypes.cdll.LoadLibrary(r'C:\Windows\System32\fbwflib.dll')
    dllObject.FbwfIsFilterEnabled.argtypes = [ctypes.POINTER(ctypes.c_bool), ctypes.POINTER(ctypes.c_bool)]
    dllObject.FbwfIsFilterEnabled.restype = None

    current = ctypes.c_bool()
    next = ctypes.c_bool()

    dllObject.FbwfIsFilterEnabled(ctypes.byref(current), ctypes.byref(next))
    messagebox.showinfo("", "Current: " + current + "\n" + "Next: " + next)

Я получаю ту же ошибку: процедура вызвана с недостаточным количеством аргументов (8 байтов пропущено) или неверное соглашение о вызовах

Я думаю, что решение близко, но кажется, что отсутствуют некоторые детали

РЕШЕНИЕ:

Решение, наконец, начинается с

ctypes.windll.LoadLibrary

, как это предлагается от Луки.Я удалил argtypes и restype на данный момент, и после получения значения c_long, которое может быть 0 или 1, получено логическое условие.

Простой (я могу сказать это сейчас) код:

@staticmethod
def IsEnabled():
    dllObject = ctypes.windll.LoadLibrary(r'C:\Windows\System32\fbwflib.dll')
    c = ctypes.c_int()
    # dllObject.FbwfIsFilterEnabled.argtypes = [ctypes.pointer(ctypes.c_int), ctypes.pointer(ctypes.c_int)]
    # dllObject.FbwfIsFilterEnabled.restype = ctypes.c_void_p

    current = ctypes.c_int()
    next = ctypes.c_int()

    dllObject.FbwfIsFilterEnabled(ctypes.byref(current), ctypes.byref(next))
    messagebox.showinfo("", "Current: " + str(bool(current)) + "\n" + "Next: " + str(bool(next)))

Я надеюсь, что это может быть полезно для других, чтобы не тратить так много времени, как я, на решение, близкое к исходному коду, но требующее исправления часов, также из-за "природы" этой библиотеки DLL, которая требовалавстроенная система и установка именно этой библиотеки.

Большое спасибо

1 Ответ

0 голосов
/ 20 сентября 2018

Попробуйте заменить строку

    dllObject.FbwfIsFilterEnabled.argtypes = [ctypes.c_int, ctypes.c_int]

на

    dllObject.FbwfIsFilterEnabled.argtypes = [POINTER(ctypes.c_int), POINTER(ctypes.c_int)]

Я также отмечаю, что функция определена так, чтобы возвращать UIntPtr, поэтому вы также можете попробовать заменитьline

    dllObject.FbwfIsFilterEnabled.restype = None

с

    dllObject.FbwfIsFilterEnabled.restype = c_void_p

Однако у меня нет копии этой DLL, поэтому я не могу проверить, работает ли это изменение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...