1

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.

Mehdi
  • 40
  • 6

1 Answers1

1

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 = IntPtr

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))
# ...
CristiFati
  • 38,250
  • 9
  • 50
  • 87
  • 1
    Thanks for the amazing solution, and the pro tips too! it worked ! i guess the workaround this one was the `ctypes.byref()` function. since the arguments are passed by reference in the c# code ! again, thanks a bunch. – Mehdi Sep 01 '23 at 11:58
  • IIRC in C# `IntPtr` is an integer of pointer *size*, not a pointer to integer, so the `restype` should be `c_int32` or `c_int64` depending on the pointer size of the OS. – Mark Tolonen Sep 01 '23 at 14:16
  • Actually see [here](https://stackoverflow.com/q/1148177/235698). `c_void_p` could also work, since `ctypes` reports its value as an integer already and it would be sized appropriately for a 32- or 64-bit OS. – Mark Tolonen Sep 01 '23 at 14:20