ctypes, python3.8 : OSError: exception: access violation writing 0x00000000

0

i want to run a dll via python 3.8 i have a function in my dll part which is :

void DLLAPI __stdcall GenerateReport (
    int             SeqContext,
    char*           szHost,
    char*           szDBName,
    char*           szUser,
    char*           szPasswd,
    const char*     szUut_Result_Id,
    char            szStylesheet[MAX_PATHNAME_LEN],
    char            szDestinationDir[MAX_DIRNAME_LEN],
    char            szPrefix[MAX_FILENAME_LEN],
    char            szFileName[MAX_PATHNAME_LEN],
    char            szPathName[MAX_PATHNAME_LEN],
    short*          psErrorOccurred,
    long*           plErrorCode,
    char            szErrorMessage[1024]
    );

For a python part i did like this :

def PrintReport():
    szNom_PV_Court = ''
    szErrormessage = ''
    sErrorok = 0
    lErrorcode = 0

    worker_ = cdll.LoadLibrary("D:\\users\\Worker.dll")

    if (worker_ == 0):
        print( " Could not open file DLL")

    worker_.GenerateReport( 0, "localhost" ,  "backend" , "user" , "test12", str( Uut_Result_Id ) , "D:\\users\\py\\ResourceFiles\\Gen.xsl" , "D:\\users\\py","" ,szNom_PV_Court , "D:\\users\\py" ,sErrorok ,lErrorcode ,szErrormessage )

when i execute my code i get error : OSError: exception: access violation writing 0x0000000

I'dont understand this error please help

python
c
ctypes
asked on Stack Overflow Mar 3, 2020 by TheRight

2 Answers

2

Strings like "localhost" in Python 3 are Unicode strings and translated to wchar_t* by ctypes. Use b'localhost' for byte strings that are translated to char*.

Also, define .argtypes and .restype for your function to for ctypes to marshal your parameters properly:

worker_.argtypes = c_int,c_char_p,c_char_p,c_char_p,c_char_p,c_char_p,c_char_p,c_char_p,c_char_p,c_char_p,c_char_p,POINTER(c_short),POINTER(c_long),c_char_p
worker_.restype = None

You also only have 13 parameters in your call but 14 are defined for the function.

Use the following for the short* and long* to create instances that can be passed to the call. Right now you are passing a zero as the default c_int which is probably the source of the null pointer exception.

sErrorok = c_short()
lErrorcode = c_long()

Call using byref(sErrorok) and byref(lErrorcode) to pass to the call as pointers.

Here's a complete example. I skipped the many input strings and just show one for reference:

test.c

#include <stdio.h>
#include <string.h>

#define DLLAPI __declspec(dllexport)

void DLLAPI __stdcall GenerateReport (
    int             SeqContext,
    char*           szHost,
    short*          psErrorOccurred,
    long*           plErrorCode,
    char            szErrorMessage[1024]
    )
{
    printf("SeqContext = %d szHost = %s\n",SeqContext,szHost);
    *psErrorOccurred = 5;
    *plErrorCode = 123;
    strcpy_s(szErrorMessage,1024,"error message");
}

test.py

from ctypes import *

szNom_PV_Court = ''
szErrormessage = ''
sErrorok = 0
lErrorcode = 0

dll = WinDLL('./test.dll')
dll.GenerateReport.argtypes = c_int,c_char_p,POINTER(c_short),POINTER(c_long),c_char_p
dll.GenerateReport.restype = None

err_occurred = c_short()
errcode = c_long()
errmsg = create_string_buffer(1024)

dll.GenerateReport(7,b'localhost',byref(err_occurred),byref(errcode),errmsg)
print(err_occurred.value,errcode.value,errmsg.value.decode())

Output:

SeqContext = 7 szHost = localhost
5 123 error message
answered on Stack Overflow Mar 3, 2020 by Mark Tolonen • edited Mar 4, 2020 by Mark Tolonen
1

You hadn't filled all strings for DLL, so they was initialized to zero. Your dll is trying to read from address 0x0 (zero) and getting smacked by OS for this. Fill all required fields with proper values.

answered on Stack Overflow Mar 3, 2020 by George Shuklin

User contributions licensed under CC BY-SA 3.0