1

I'm trying to make use of a SecuGen Fingerprint scanner using Python, the SDK lib I'm using is sgfplib.dll. I have a C++ program that makes use of this DLL and access the hardware using C++ and the very same DLL. I can also access the device using the Windows Biometric Framework (winbio.dll), Python and ctypes but this framework don't have the functionallity I need.

The thing is, using the sgfplib.dll, after creation of the main library object I get a handle of the dll just fine, but anytime I try to call any other function I'll get an OSError: exception: access violation reading|writing 0x###########.

I've searched both the site and google looking for similar errors but nothing seems close to my problem. I got the DLLs in my system32 folder and I also tried putting them in the scripts dir without any luck

The address in the error does change if I change the devname or if I call a diff function.

Can anyone point me in the right direction or provide some more info on this kind of errors?

Here's a min reproducible example:

import ctypes
from ctypes import wintypes

lib = ctypes.WinDLL(r"..\pathToTheDLLsDir\sgfplib.dll")
session_handle = ctypes.c_uint32()
devname = ctypes.wintypes.DWORD()
devname = "SG_DEV_FDU05" # 5

err = lib.SGFPM_Create(ctypes.byref(session_handle)) # create an SGFPM object and 
print('CREATE', err) # 0                             # return a handle to the object

err = lib.SGFPM_Init(ctypes.byref(session_handle), devname) # OSError: exception: access 
print('INIT', err)                                          # violation reading 0x00000000AFE3FB10
Solrac
  • 924
  • 8
  • 23

1 Answers1

1

Listing [Python.Docs]: ctypes - A foreign function library for Python.

The error is widely encountered, I've answered a bunch of questions (on the same topic) here on SO.
Code is full of Undefined Behaviors. The most common one is [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer), encountered when calling functions.

Found SecuGen references (no official ones unfortunately):

I prepared a dummy example (downloaded a .dll for testing purposes, but couldn't fully test since I don't have the device).

code00.py:

#!/usr/bin/env python

import ctypes as cts
import ctypes.wintypes as wts
import sys


HSGFPM = cts.c_void_p

DLL_NAME = "./sgfplib.{:s}".format("dll" if sys.platform[:3].lower() == "win" else "so")

# @TODO - cfati: Can add all constants here
SG_DEV_FDU04 = 0x05
SG_DEV_FDU05 = 0x06


def is_error(error_code):
    # @TODO - cfati: Assume functions return 0 on success
    if error_code != 0:
        return True
    return False


def main(*argv):
    dll = cts.WinDLL(DLL_NAME)
    SGFPM_Create = dll.SGFPM_Create
    SGFPM_Create.argtypes = (cts.POINTER(HSGFPM),)
    SGFPM_Create.restype = wts.DWORD
    SGFPM_Init = dll.SGFPM_Init
    SGFPM_Init.argtypes = (HSGFPM, wts.DWORD)
    SGFPM_Init.restype = wts.DWORD
    SGFPM_Terminate = dll.SGFPM_Terminate
    SGFPM_Terminate.argtypes = (HSGFPM,)
    SGFPM_Terminate.restype = wts.DWORD

    handle = HSGFPM()

    res = SGFPM_Create(cts.byref(handle))
    if is_error(res):
        print("Error SGFPM_Create: {:d}".format(res))
        return

    dev = SG_DEV_FDU04

    res = SGFPM_Init(handle, dev)
    if is_error(res):
        print("Error SGFPM_Init: {:d}".format(res))
        SGFPM_Terminate(handle)
        return

    # Do your thing

    SGFPM_Terminate(handle)


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.\n")
    sys.exit(rc)
CristiFati
  • 38,250
  • 9
  • 50
  • 87
  • 1
    Thanks, I realized later that day how bad I messed up though your code and references taught me how to correctly initialize external libraries and their methods. This is my first time using Python and also first time using DLL's. Everything is working now!! – Solrac Jul 31 '23 at 16:52