Working with Python 3.8, I am trying to call the following function of a C dll:
extern void* __stdcall Reentrante_CreerNouvelleIdentification
(
int NumeroDuCapteur ,
DetectorType_t DetectorType,
float DetectorVolume,
float Resolution,
float ResolutionCzt,
float C1 ,
float C2 ,
float C3 ,
float C4 ,
unsigned char CustomLibrary[NB_ISOTOPES_CANDIDAT],
float FeThick,
float CdThick,
float PbThick,
int maxIsoPourReportingIdent,
const char* BkgPath
);
Using the following Python code:
# Read dll with Python.
import os
import ctypes as ct
WorkFolder = "C:/Data/SOFTS/SMI_5510"
os.add_dll_directory(WorkFolder)
SIA = ct.cdll.LoadLibrary("SIA_Identification.dll")
n = 70
CustomLib = ct.c_ubyte*n
tab = [0]*n
# Calling Reentrante_CreerNouvelleIdentification.
SIA.Reentrante_CreerNouvelleIdentification.restype = ct.c_void_p
SIA.Reentrante_CreerNouvelleIdentification.argtypes = [ct.c_int,
ct.c_int, ct.c_float, ct.c_float, ct.c_float,
ct.c_float, ct.c_float, ct.c_float, ct.c_float,
ct.c_ubyte,
ct.c_float, ct.c_float, ct.c_float,
ct.c_int, ct.c_char_p]
s = SIA.Reentrante_CreerNouvelleIdentification(666,
0, 250, 7.5, 12.5,
1, 0, 0, 0,
CustomLib(*tab),
0, 0, 0,
5, None)
I get the following error message telling me that my CustomLib
array is not correctly defined:
Traceback (most recent call last):
File "C:\Users\xxxx\Desktop\code.py", line 23, in <module>
s = SIA.Reentrante_CreerNouvelleIdentification(666,
ArgumentError: argument 10: <class 'TypeError'>: wrong type
What is the correct type?
I changed my Python code as follows based on Mark Tolonen's answer:
# Read dll with Python.
import os
import ctypes as ct
WorkFolder = "C:/Data/SOFTS/SMI_5510"
os.add_dll_directory(WorkFolder)
SIA = ct.WinDLL("C:/Data/SOFTS/SMI_5510/SIA_Identification.dll")
n = 70
CustomLib = ct.c_ubyte*n
tab = [0]*n
# Calling Reentrante_CreerNouvelleIdentification.
SIA.Reentrante_CreerNouvelleIdentification.restype = ct.c_void_p
SIA.Reentrante_CreerNouvelleIdentification.argtypes = [ct.c_int,
ct.c_int, ct.c_float, ct.c_float, ct.c_float,
ct.c_float, ct.c_float, ct.c_float, ct.c_float,
ct.POINTER(ct.c_ubyte),
ct.c_float, ct.c_float, ct.c_float,
ct.c_int, ct.c_char_p]
s2 = SIA.Reentrante_CreerNouvelleIdentification(666,
0, 250, 7.5, 12.5,
1, 0, 0, 0,
CustomLib(*tab),
0, 0, 0,
5, None)
I now get the following error:
Traceback (most recent call last):
File "C:\Users\xxxx\Desktop\code.py", line 23, in <module>
s2 = SIA.Reentrante_CreerNouvelleIdentification(666,
OSError: exception: access violation writing 0x00000014
CustomLibrary
is an array (unsigned char CustomLibrary[NB_ISOTOPES_CANDIDAT]
), but arrays decay to pointers in parameters, so the correct type could be ct.POINTER(ct.c_ubyte)
, although CustomLib
could be used as well. Python will do the additional size checking on the input if an array is used, but will still marshal a pointer.
As an aside, a __stdcall
function should use WinDLL
instead of CDLL
, but you won't see an issue using the wrong one on 64-bit Python where there is only one calling convention. Below would work on 32-bit Python as well:
SIA = ct.WinDLL("C:/Data/SOFTS/SMI_5510/SIA_Identification.dll")
test.cpp
#include <stdio.h>
extern "C" {
typedef int DetectorType_t;
#define NB_ISOTOPES_CANDIDAT 70
__declspec(dllexport)
extern void* __stdcall Reentrante_CreerNouvelleIdentification(
int NumeroDuCapteur,
DetectorType_t DetectorType,
float DetectorVolume,
float Resolution,
float ResolutionCzt,
float C1,
float C2,
float C3,
float C4,
unsigned char CustomLibrary[NB_ISOTOPES_CANDIDAT],
float FeThick,
float CdThick,
float PbThick,
int maxIsoPourReportingIdent,
const char* BkgPath)
{
printf("%s\n",CustomLibrary);
return nullptr;
}
}
test.py
import os
import ctypes as ct
SIA = ct.WinDLL('./test')
n = 70
CustomLib = ct.c_ubyte * n
tab = [104,101,108,108,111] # byte values of ASCII 'hello'
SIA.Reentrante_CreerNouvelleIdentification.restype = ct.c_void_p
SIA.Reentrante_CreerNouvelleIdentification.argtypes = (
ct.c_int, ct.c_int, ct.c_float, ct.c_float, ct.c_float,
ct.c_float, ct.c_float, ct.c_float, ct.c_float,
ct.POINTER(ct.c_ubyte),
ct.c_float, ct.c_float, ct.c_float, ct.c_int, ct.c_char_p)
s = SIA.Reentrante_CreerNouvelleIdentification(
666, 0, 250, 7.5, 12.5,
1, 0, 0, 0,
CustomLib(*tab),
0, 0, 0, 5, None)
Output:
C:\>test.py
hello
User contributions licensed under CC BY-SA 3.0