Python ctypes identifying dll function result
Question: I have some functions according to a DLL's documentation (there are more):

    
    
    # there are 2 lines in the other example like this
    # define CALLTYPE __stdcall
    # define pLSenvL void*
    
    pLSenvL CALLTYPE LScreateEnvL()
    int LSopenLogFileL( pLSenvL pL, char *pcLogFile)
    int CALLTYPE LSsetPointerL(pLSenvL pL, double* pdPointer, int* pnPointersNow)
    int LSexecuteScriptL( pLSenvL pL, char* pcScript)
    int LScloseLogFileL( pLSenvL pL)
    void LSclearPointers( pLSenvL pL)
    

What I've done so far is this:

    
    
    from ctypes import *
    
    api = CDLL("PATH_TO_DLL")
    pLEnv = api.LScreateEnvL()
    script = "STRING FULL OF COMMANDS"
    
    print api.LSexecuteScriptL(pLEnv, script)
    

and it works, but now I want to replicate an example I found:

    
    
    void CSDlg::OnSolve()
    {
      int nError, nPointersNow;
    
      CString csScript, cs;
      double dNeeds[1], dStart[1];
    
      dNeeds[ 0] = (double) nNeedsM;
    
      pLSenvL pL;
      pL = LScreateEnvL();
    
      nError = LSopenLogFileL( pL, "log_file.log");
      nError = LSsetPointerL( pL, dNeeds, &nPointersNow);
      nError = LSsetPointerL( pL, dStart, &nPointersNow);
    
      csScript = "SET ECHOIN 1\n";
    
      // Run the script
      nError = LSexecuteScriptL( pL, (LPCTSTR) csScript);
      // Close the log file 
      LScloseLogFileL( pL);
      csStartM.Format( "%d", (int) dStart[0]);
    }
    

So far I've done this:

    
    
    nError = c_int
    nPointersNow = c_int
    
    dNeeds = c_double()
    #I'm just setting a random value
    dNeeds = [c_double(10)]
    
    pLEnv = api.LScreateEnvL()
    nError = api.LSopenLogFileL(pLEnv, "log_file.log")
    # here I got 
    # Procedure called with not enough arguments (8 bytes missing) or wrong calling convention
    nError = api.LSsetPointerL(pLEnv, byref(dNeeds), nPointersNow)
    # and here I got
    # byref argument must be a ctypes instance, not 'list'
    

So I've searched and I had to do something like this

    
    
    #now here comes my problem
    #according to documentation it is
    #  int CALLTYPE LSsetPointerL(pLSenvL pL, double* pdPointer, int* pnPointersNow)
    api.LSsetPointerL.restype = c_int
    api.LSsetPointerL.argtypes = [ ¿?, c_double, c_int]
    

  * What should go as first element in that array of argtypes?? 
  * Is there something I have to worry about the CALLTYPE definition?

Thanks in advance


Answer: "`Procedure called with not enough arguments (8 bytes missing) or wrong
calling convention`" refers to how you called the DLL. You used CDLL, but it
says "`# define CALLTYPE __stdcall`", so you should used WinDLL instead ([see
ctypes docs](https://docs.python.org/2/library/ctypes.html)). This sometimes
works regardless but seems to be failing on the more complicated calls.

You are not instantiating `nPointersNow`, you probably mean `nPointersNow()`.

You can't set `dNeeds` to be a list. Maybe you mean:

    
    
    somefunc.argtypes = [c_double()]
    dNeeds = c_double(10)
    nError = api.LSsetPointerL(pLEnv, byref(dNeeds), nPointersNow)
    

And the type `plSenvL` should be defined somewhere in your docs.
`LScreateEnvL` returns that type, as shown here:

    
    
    pLSenvL CALLTYPE LScreateEnvL()
    pLSenvL __stdcall LScreateEnvL() (<- what the above line really means)
    

so you need to know what it is. We can guess that it's a pointer (an integer)
to something called `LSenvL`, which you will possibly need to make a structure
for. Not hard, but you need to know how it's defined. That said, you may be
able to avoid it since the first function returns it. So if you don't need to
use it directly you could try and dodgy it like this:

    
    
    LScreateEnvL = api.LScreateEnvL
    LScreateEnvL.restype = c_int   # just assume it's an int
    
    LSopenLogFileL = api.LSopenLogFileL
    LSopenLogFileL.restype = c_int
    LSopenLogFileL.argtypes = (c_int,   # again just assume
                               c_char_p)
    
    LSsetPointerL = api.LSsetPointerL
    LSsetPointerL.restype = c_int
    LSsetPointerL.argtypes = (c_int,   # assume int
                              POINTER(c_double),
                              POINTER(c_int))
    
    pLSenvL = LScreateEnvL()
    
    dPointer = c_double()
    nPointersNow = c_int()
    nError = LSsetPointerL(pLSenvL,
                           byref(dPointer),
                           byref(nPointersNow))
    

