Python Load Windows библиотека преобразования C #

1

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

В С# мой код:

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, как предложил Luke (спасибо), теперь у меня была другая ошибка:

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

относится к строке:

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

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

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

Я получаю сообщение об ошибке: Ошибка типа: должен быть тип ctypes

что дайте мне знать, что, по-видимому, правильное обращение было правильным.

изменяя рассматривая тип bool как сделано на моем С# code:

@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 a, получили логическое условие.

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

@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)))

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

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

Теги:
ctypes

1 ответ

0

Попробуйте заменить линию

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

с

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

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

    dllObject.FbwfIsFilterEnabled.restype = None

с

    dllObject.FbwfIsFilterEnabled.restype = c_void_p

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

  • 0
    Большое спасибо за ответ. Я отредактировал свой вопрос с помощью другого теста, основанного на вашем предложении. Я могу сказать, что это не работает, но я думаю, что решение ближе, чем раньше. Да, эта dll не является обычной dll, но обычно доступна во встроенной системе и особенно в Windows-версии POS. Меня также интересуют примеры других dll, в которых есть функции, вызываемые по ссылке, чтобы проверить, как получить правильный вызов даже для другой dll. В этом случае вы знаете некоторые функции Windows DLL, которые можно использовать в качестве предварительного теста? Большое спасибо
  • 0
    UIntPtr функция возвращает что-то ( UIntPtr по ссылке). Однако вы установили его restype на None . Поможет ли вам изменить тип возврата в соответствии с моим отредактированным вопросом?
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню