1

I have managed to initialize my dll and to call functions from it using ctypes. I am also able to retrieve the content of output parameters passed by reference to those functions. The output parameters that I have success with are either c_int or c_double. However, I am unable to retrieve the content of those output parameters when they should contain a string and for which I am using the c_wchar_p.

Here is the code. First, I set all my variables. Then, I call the function.

    in_Iresult=ctypes.c_int(1) #Desired result line, from 0 up to Nresult-1
    out_LaufradBez=ctypes.c_wchar_p() #Fan wheel designation
    out_LaufradPdf=ctypes.c_wchar_p() #(if available) Path and file name of fan wheel data sheet 
    out_GehaeuseBez=ctypes.c_wchar_p() #Housing designation, if with housing
    out_GehaeusePdf=ctypes.c_wchar_p() #(if available) Path and file name of housingdata sheet
    out_GehaeuseOefWkl=ctypes.c_wchar_p() #housing angle, if with housing
    out_EinstrBez=ctypes.c_wchar_p() #Designation of inlet cone, if with inlet cone
    out_EinstrPdf=ctypes.c_wchar_p() #(if available) Path and file name of inlet cone data sheet
    out_BildS=ctypes.c_wchar_p() #(if available) Path and file name of drawing 
    out_BildB=ctypes.c_wchar_p() #(if available) Path and file name of image
    out_V=ctypes.c_double() #Volume flow
    out_dP_fa=ctypes.c_double() #Pressure (static)
    out_dP_tot=ctypes.c_double() #Pressure (total)
    out_LpA=ctypes.c_double() #Sound pressure level, A-weighted
    out_LwA=ctypes.c_double() #Sound power level, A-weighted
    out_n=ctypes.c_double() #Speed
    out_Pwe=ctypes.c_double() #Shaft power
    out_PweMax=ctypes.c_double() #Max shaft power (over complete flow range)
    out_Eta_fa=ctypes.c_double() #Mechanical efficiency static
    out_Eta_tot=ctypes.c_double() #Mechanical efficiency total
    out_EinbauBreite=ctypes.c_double() #Unit lenght
    out_Ueberlappung=ctypes.c_double() #Axile gap
    out_Anmerkung=ctypes.c_void_p() #Annotations to fan

    Result=PunkerDLL.CAT_RESULTW(in_Iresult,
                                 ctypes.byref(out_LaufradBez),
                                 ctypes.byref(out_LaufradPdf),
                                 ctypes.byref(out_GehaeuseBez),
                                 ctypes.byref(out_GehaeusePdf),
                                 ctypes.byref(out_GehaeuseOefWkl),
                                 ctypes.byref(out_EinstrBez),
                                 ctypes.byref(out_EinstrPdf),
                                 ctypes.byref(out_BildS),
                                 ctypes.byref(out_BildB),
                                 ctypes.byref(out_V),
                                 ctypes.byref(out_dP_fa),
                                 ctypes.byref(out_dP_tot),
                                 ctypes.byref(out_LpA),
                                 ctypes.byref(out_LwA),
                                 ctypes.byref(out_n),
                                 ctypes.byref(out_Pwe),
                                 ctypes.byref(out_PweMax),
                                 ctypes.byref(out_Eta_fa),
                                 ctypes.byref(out_Eta_tot),
                                 ctypes.byref(out_EinbauBreite),
                                 ctypes.byref(out_Ueberlappung),
                                 ctypes.byref(out_Anmerkung))

    print("L'extraction de données de fan a fonctionné si 0 :",Result)
    s = "Hello, world!"
    c_s = ctypes.c_wchar_p(s)
    print(c_s)
    print(c_s.value)
    print(out_n)
    print(out_n.value)
    print(out_LaufradBez)
    print(out_LaufradBez.value)

I have no trouble printing out "Hello, world!" in the terminal nor do I have trouble printing the value of an output parameter that is a c_double type, such as out_n. However, it seems like I can't print the value of a c_void_p parameter. It makes the program crash.

See printout from terminal :

L'extraction de données de fan a fonctionné si 0 : 0
c_wchar_p(2565936992944)
Hello, world!
c_double(1354.0)
1354.0
c_wchar_p(29555362188230724)

As you can see, the printout value of out_LaufradBez.value does not compile/execute. As you can see, there is something in the memory, but it's unable to print the value out.

Is there a way to print out the value using another method than print()? Else, is there a way to know what is the error that makes the program crash?

Basically, I know the DLL function has worked properly, and I know that the variable has a content, but I am unable to print its value.

Please halp

JH95
  • 21
  • 3
  • Please also post the *CAT\_RESULTW* function (*C*) header. Regarding the crash, it's [\[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), or at least one of them. Also, this (a function with 23 arguments) smells like a bad bad design. – CristiFati Nov 15 '21 at 21:26
  • With so many parameters, you'd be better off passing a single structure instead. – Mark Tolonen Nov 16 '21 at 16:44
  • You are right... First python and C DLL usage experience, so there are still some concept that i need to get a grasp of... Will get there, mr. Tolonen! Thank you for taking the time to address my question. – JH95 Nov 16 '21 at 17:02

1 Answers1

1

If you look at the value of the out_LaufradBez pointer as hex, you will see that what was written to the c_wchar_p was not a pointer, but UTF-16 data:

>>> x=29555362188230724
>>> hex(x)
'0x69007200700044'
>>> x.to_bytes(8,'little').decode('utf-16le')
'Dpri'

This indicates the API takes a wchar_t* not a wchar_t** but the prototype wasn't shown. I suspect the API should be passed a pre-allocated buffer using ctypes.create_unicode_buffer(size) instead of the address of a pointer.

Update your question with the actual C prototype for more guidance.

Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251