Search code examples
pythonc#c++djangoctypes

imported some function from c++ dll to python using ctypes, but some functions doesn't work as expected


so i'm developing a backend using django and i got an image processing step for which i'm using a private c++ .dll developed by my company. i'm using ctypes to load the .dll file and managed to make some of the imported functions work properly. but some functions ("fr_get_fire_img" in this case) doesn't work as expected. i don't know if i am specifying the function's argtypes or the function restype incorrectly and need some guide, thanks in advance!

here's the function signature in c#:

[DllImport(DLL_NAME)]
public static extern IntPtr fr_get_fire_img(byte instance, ref short W, ref short H, ref short step); 

here's the python code where i'm trying to use the imported function:

import ctypes
from ctypes import c_char_p as char_pointer
from ctypes import c_short as short
from ctypes import c_void_p as int_pointer


zero = char_pointer(0)

w = short(0)
h = short(0)
step = short(0)

fire_dll.fr_get_fire_img.restype = int_pointer
source = fire_dll.fr_get_fire_img(zero, w, h, step)
print(source, type(source))

and finally this is the error i'm getting from ctypes:

Traceback (most recent call last):
  File "PATH OF PYTHON FILE", line 44, in <module>
    source = fire_dll.fr_get_fire_img(zero, w, h, step)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: exception: access violation writing 0x0000000000000000

i couldn't find any reference online so i'd appreciate some help or guidance.


Solution

  • Before everything, check [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer) for a common pitfall when working with CTypes (calling functions).

    If your C# function header is correct, here's how it should look in Python (although an instance of type byte and a value of 0 doesn't look right to me):

    import ctypes as cts
    
    # ...
    #IntPtr = cts.POINTER(cts.c_int)
    ShortPtr = cts.POINTER(cts.c_short)
    
    fr_get_fire_img = fire_dll.fr_get_fire_img
    fr_get_fire_img.argtypes = (cts.c_ubyte, ShortPtr, ShortPtr, ShortPtr)
    fr_get_fire_img.restype = cts.c_void_p  # @TODO: C#
    
    instance = 0
    h = cts.c_short(0)
    w = cts.c_short(0)
    step = cts.c_short(0)
    
    res = fr_get_fire_img(instance, cts.byref(w), cts.byref(h), cts.byref(step))
    # ...