Advice dealing with Undefined Behavior in Python using Ctypes - OSError:exception:access violation reading 0x00000000000000000

833 Views Asked by At

I am using Python 3.8.8 (64-bit) to interface with a device (Meadowlark Spatial Light modulator) using ctypes 1.1.0 to read the provided DLL file and send data to the device. I am using Windows 11 Pro for Workstations.

I am seeing Undefined Behavior where sometimes everything works, sometimes it hangs, and sometimes I receive OSError:exception:access violation reading 0x00000000000000000. I am thinking it must be an error in how I am using ctypes in Python. I have tried different ways to load the DLL file (i.e., WinDLL vs CDLL). I have also gone and added the argtypes and restyle to make sure I am sending the correct types to each function based on PYTHON - Ctypes : OSError: exception: access violation writing 0xFFFFFFFFFA1C001B. The error always occurs for slm_lib.Write_image() -- see code below. Clearly, I am missing something, any advice on how to track the source of the error down would be great.

I have also attached the corresponding header file for reference.

import numpy
import ctypes as ct
from scipy import misc
from time import sleep
import matplotlib.pyplot as plt
import numpy as np
import scipy.ndimage as ndi


#Load the DLL
#Blink_C_wrapper.dll, Blink_SDK.dll, ImageGen.dll, FreeImage.dll and wdapi1021.dll
#should all be located in the same directory as the program referencing the
#library
ct.cdll.LoadLibrary("C:\\Program Files\\Meadowlark Optics\\Blink OverDrive Plus\\SDK\\Blink_C_wrapper")
slm_lib = ct.WinDLL("Blink_C_wrapper")
try:
    slm_lib.Delete_SDK()
    sleep(1)
except:
    pass
slm_lib = ct.WinDLL("Blink_C_wrapper")


# Basic parameters for calling Create_SDK
bit_depth = ct.c_uint(12)
num_boards_found = ct.c_uint(0)
constructed_okay = ct.c_int(0)
is_nematic_type  = ct.c_int(1)
RAM_write_enable = ct.c_int(1)
use_GPU = ct.c_int(1)
max_transients = ct.c_int(10)
board_number = ct.c_int(1)
wait_For_Trigger = ct.c_int(0)
output_Pulse = ct.c_int(0)
timeout_ms = ct.c_uint(5000)
center_x = ct.c_float(1152)
center_y = ct.c_float(1920)

# Call the Create_SDK constructor
# Returns a handle that's passed to subsequent SDK calls
slm_lib.Create_SDK.argtypes=[ct.c_uint, ct.POINTER(ct.c_uint),ct.POINTER(ct.c_int), ct.c_int, ct.c_int,  ct.c_int, ct.c_int, ct.c_char_p]
slm_lib.Create_SDK.restyle=ct.c_int
slm_lib.Create_SDK(bit_depth,ct.byref(num_boards_found), 
                    ct.byref(constructed_okay), is_nematic_type, 
                    RAM_write_enable, use_GPU, max_transients, None)# "SLM_lut.txt")

slm_lib.Write_image.argtypes=[ct.c_int,ct.POINTER(ct.c_ubyte),ct.c_uint, ct.c_int, ct.c_int, ct.c_uint ]
slm_lib.Write_image.restyle=ct.c_int

slm_lib.ImageWriteComplete.argtypes=[ct.c_int, ct.c_uint]#(board_number, timeout_ms);
slm_lib.ImageWriteComplete.restyle=ct.c_int

if constructed_okay == -1:
    print ("Blink SDK was not successfully constructed");
    # Python ctypes assumes the return value is always int
    # We need to tell it the return type by setting restype
    slm_lib.Get_last_error_message.restype = ct.c_char_p
    print (slm_lib.Get_last_error_message());

    # Always call Delete_SDK before exiting
    slm_lib.Delete_SDK()
else:
    # try:
    print ("Blink SDK was successfully constructed");
    print ("Found %s SLM controller(s)" % num_boards_found.value);
    
    height = ct.c_uint(slm_lib.Get_image_height(board_number));
    width = ct.c_uint(slm_lib.Get_image_width(board_number));
    ImageOne = numpy.empty([width.value*height.value], numpy.uint8, 'C');
    ImageOne*=0
    center_x =  ct.c_uint(width.value//2);
    center_y =  ct.c_uint(height.value//2);
    
    slm_lib.Write_image(board_number, ImageOne.ctypes.data_as(ct.POINTER(ct.c_ubyte)), ct.c_uint(height.value*width.value), wait_For_Trigger, output_Pulse, timeout_ms)
    slm_lib.ImageWriteComplete(board_number, timeout_ms); 

The corresponding header file for Blink_C_wrapper

//
//:  Blink_SDK_C_wrapper for programming languages that can interface with DLLs
//
//   (c) Copyright Meadowlark Optics 2017, All Rights Reserved.


#ifndef BLINK_C_WRAPPER_H_
#define BLINK_C_WRAPPER_

#ifdef BLINK_C_WRAPPER_EXPORTS
#define BLINK_C_WRAPPER_API __declspec(dllexport)
#else
#define BLINK_C_WRAPPER_API __declspec(dllimport)
#endif


#ifdef __cplusplus
extern "C" { /* using a C++ compiler */
#endif

  BLINK_C_WRAPPER_API void Create_SDK(unsigned int SLM_bit_depth,
                                      unsigned int* n_boards_found,
                                      int *constructed_ok,
                                      int is_nematic_type,
                                      int RAM_write_enable,
                                      int use_GPU_if_available,
                                      int max_transient_frames,
                                      char* static_regional_lut_file);

  BLINK_C_WRAPPER_API void Delete_SDK();

  BLINK_C_WRAPPER_API
  int Is_slm_transient_constructed();

  BLINK_C_WRAPPER_API
  int Write_overdrive_image(int board,
                            unsigned char* target_phase,
                            int wait_for_trigger,
                            int external_pulse,
                            unsigned int trigger_timeout_ms);

  BLINK_C_WRAPPER_API
  int Calculate_transient_frames(unsigned char* target_phase,
                                 unsigned int* byte_count);

  BLINK_C_WRAPPER_API
  int Retrieve_transient_frames(unsigned char* frame_buffer);

  BLINK_C_WRAPPER_API
  int Write_transient_frames(int board,
                             unsigned char* frame_buffer,
                             int wait_for_trigger,
                             int external_puls,
                             unsigned int trigger_timeout_ms);

  BLINK_C_WRAPPER_API
  int Read_transient_buffer_size(char *filename,
                                 unsigned int* byte_count);

  BLINK_C_WRAPPER_API
  int Read_transient_buffer(char *filename,
                            unsigned int byte_count,
                            unsigned char *frame_buffer);

  BLINK_C_WRAPPER_API
  int Save_transient_frames(char *filename,
                            unsigned char *frame_buffer);

  BLINK_C_WRAPPER_API
  const char* Get_last_error_message();

  BLINK_C_WRAPPER_API
  int Load_overdrive_LUT_file(char* static_regional_lut_file);

  BLINK_C_WRAPPER_API
  int Load_linear_LUT(int board);

  BLINK_C_WRAPPER_API
  const char* Get_version_info();

  BLINK_C_WRAPPER_API
  void SLM_power(int power_state);

  // ----------------------------------------------------------------------------
  //  Write_image
  // ----------------------------------------------------------------------------
  BLINK_C_WRAPPER_API
  int Write_image(int board,
                  unsigned char* image,
                  unsigned int image_size,
                  int wait_for_trigger,
                  int external_pulse,
                  unsigned int trigger_timeout_ms);

  BLINK_C_WRAPPER_API int ImageWriteComplete(int board, unsigned int trigger_timeout_ms);

  // ----------------------------------------------------------------------------
  //  Load_LUT_file
  // ----------------------------------------------------------------------------
  BLINK_C_WRAPPER_API int Load_LUT_file(int board, char* LUT_file);

  BLINK_C_WRAPPER_API int Load_LUT_Arrays(int board, const unsigned short* RampUp, const unsigned short* RampDown, const unsigned short* PreRampUp, const unsigned short* PreRampDown, const unsigned short* PostRampUp, const unsigned short* PostRampDown);

  BLINK_C_WRAPPER_API int SetRampDelay(int board, unsigned int ramp_delay);

  // ----------------------------------------------------------------------------
  //  Compute_TF
  // ----------------------------------------------------------------------------
  BLINK_C_WRAPPER_API int Compute_TF(float frame_rate);

  // ----------------------------------------------------------------------------
  //  Set_true_frames
  // ----------------------------------------------------------------------------
  BLINK_C_WRAPPER_API void Set_true_frames(int true_frames);

  BLINK_C_WRAPPER_API void Stop_sequence();

  BLINK_C_WRAPPER_API double Read_SLM_temperature(int board);

  BLINK_C_WRAPPER_API int Get_image_width(int board);

  BLINK_C_WRAPPER_API int Get_image_height(int board);

  BLINK_C_WRAPPER_API double Get_pixel_pitch(int board);

#ifdef __cplusplus
}
#endif

#endif //BLINK_C_WRAPPER_ 
0

There are 0 best solutions below