-1

I'm trying to use ctypes to call a function in a dll built by C. I'm having trouble with the input types and thus the OS error happens. The function arguments in the C code for dll:

DllExport extern double far pascal dFlComprOil (
   int               nOilCompr,    
   double            dOilGrav,    
   double            dSGGas,       
   double            dSolnGOR,     
   double            dTargetPress, 
   double            dTargetTemp,  
   double            dSepPress,     
   double            dSepTemp,     
   BOOL              bCheckRanges, 
   char          far szErrorMsg[], 
   int           far *nError) 

And my code in Python:

from ctypes import *
lib = WinDLL(r"C:\FldSP970.dll")
class SomeStructure(Structure):
    _fields_ = [
    ('nOilCompr', c_int),
    ('dOilGrav', c_double),
    ('dSGGas', c_double),
    ('dSolnGOR', c_double),
    ('dTargetPress', c_double),
    ('dTargetTemp', c_double),
    ('dSepPress', c_double),
    ('dSepTemp', c_double),
    ('bCheckRanges', c_bool),
    ('szErrorMsg[]', c_char),
    ('*nError', c_int)
    ]
lib.dFlComprOil.restype = c_double
lib.dFlComprOil.argtypes = [POINTER(SomeStructure)]
#lib.dFlComprOil.argtypes = c_int,c_double,c_double,c_double,c_double,c_double,c_double,c_double,c_bool,c_char,c_int      
s_obj = SomeStructure(0, 35, 0.65, 151.489, 861.066, 60, 100, 60,False,0,0)
result = lib.dFlComprOil(byref(s_obj))

I have fixed some errors and done experiments for the argument szErrorMsg but it gives this vague OS Error in the end. I'm guessing I'm doing something wrong with the last two arguments, but since I'm not quite familiar with C, I'm now lost. Any help or guidance would be appreciated.

OliverX
  • 3
  • 2
  • `lib.dFlComprOil.argtypes = [POINTER(SomeStructure)]` - that's not what your C says! – user2357112 Jan 03 '21 at 03:18
  • 1
    Your commented-out thing isn't what your C says either, for that matter, and `szErrorMsg[]` and `*nError` aren't argument names - you're misunderstanding how types are declared in C. – user2357112 Jan 03 '21 at 03:20
  • You got it all wrong. The arguments (with the 2 mistakes pointed out earlier) **should not be part of *SomeStructure.\_fields\_*, but *argytpes***. Might want to check [\[SO\]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer)](https://stackoverflow.com/questions/58610333/c-function-called-from-python-via-ctypes-returns-incorrect-value/58611011#58611011). – CristiFati Jan 03 '21 at 10:52

1 Answers1

0

Don't use a structure. There is no structure in the C call. Use argtypes, but your last parameters were wrong:

from ctypes import *
lib = WinDLL(r"C:\FldSP970.dll")
lib.dFlComprOil.argtypes = c_int,c_double,c_double,c_double,c_double,c_double,c_double,c_double,c_bool,c_char_p,POINTER(c_int)
lib.dFlComprOil.restype = c_double
# Likely the last two parameters are output values, so allocate some amount of storage.
# Consult the function documentation...the size requirements aren't obvious.
errmsg = create_string_buffer(1024)  # equivalent to char[1024];
nerror = c_int()                     # A single C integer for output.
result = lib.dFlComprOil(0, 35, 0.65, 151.489, 861.066, 60, 100, 60,False,errmsg,byref(nerror))
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
  • Thank you so much for the help. I have zero experience in C so the question seems dumb. Thank you anyway! This works. – OliverX Jan 05 '21 at 04:47