2

I am trying to access a C++ dll from python (I am new to Python). I overcame many calling convention issues and finally got it to run without any compile/linking error. However when I print the returning array from C++ dll in python it shows all random initialized values. It looks like the values were not correctly returned.

My C++ code looks like this.

double DLL_EXPORT __cdecl *function1(int arg1, int arg2, double arg3[],int arg4,double arg5,double arg6,double arg7, double arg8)
{     
        double *Areas = new double[7];

        ....Calculations

        return Areas;
}

My python code looks as follows:

import ctypes

CalcDll = ctypes.CDLL("CalcRoutines.dll")

arg3_py=(ctypes.c_double*15)(1.926,1.0383,0.00008,0.00102435,0.0101,0.0,0.002,0.0254,102,1,0.001046153,0.001046153,0.001046153,0.001046153,20)
dummy = ctypes.c_double(0.0)

CalcDll.function1.restype = ctypes.c_double*7
Areas = CalcDll.function1(ctypes.c_int(1),ctypes.c_int(6),arg3_py,ctypes.c_int(0),dummy,dummy,dummy,dummy)

for num in HxAreas:
    print("\t", num)

The output of the print statement is as below:

     2.4768722583947873e-306
     3.252195577561737e+202
     2.559357001198207e-306
     5e-324
     2.560791130833573e-306
     3e-323
     2.5621383435212475e-306

Any suggestion on what I am doing wrong is greatly appreciated.

10
  • 1
    Note that functions returning structs do not always do this the same way for different compilers (I learnt this the hard way). The way your C++ compiler returns such structs may be incompatible with the way your version of Python expects. Commented Jul 21, 2016 at 20:44
  • stackoverflow.com/a/6731737/95954 Commented Jul 21, 2016 at 20:51
  • 2
    It is probably better to return an array of doubles that has been allocated with malloc() so it can be deallocated by ctypes. Commented Jul 21, 2016 at 20:54
  • Also: stackoverflow.com/a/6726624/95954 Commented Jul 21, 2016 at 21:04
  • 1
    @J.J.Hakala: only if ctypes is able to use the identical memory manager. That is very unlikely when the C memory manager is in a DLL and ctypes is not. See the link in my third comment: pass an explicit poibter to a buffer allocated by the caller. The DLL only copies into the buffer. Commented Jul 21, 2016 at 21:09

1 Answer 1

2

Instead of

CalcDll.function1.restype = ctypes.c_double * 7

there should be

CalcDll.function1.restype = ctypes.POINTER(ctypes.c_double)

and then

Areas = CalcDll.function1(ctypes.c_int(1), ctypes.c_int(6), arg3_py,
                          ctypes.c_int(0), dummy, dummy, dummy, dummy)

for i in range(7):
    print("\t", Areas[i])

I'm not sure what ctypes does in case of 'ctypes.c_double * 7', if it tries to extract seven double from the stack or what.

Tested with

double * function1(int arg1, int arg2, double arg3[],
                   int arg4, double arg5, double arg6,
                   double arg7, double arg8)
{
    double * areas = malloc(sizeof(double) * 7);
    int i;

    for(i=0; i<7; i++) {
        areas[i] = i;
    }

    return areas;
}

the values in the array are printed correctly with restype = ctypes.POINTER(ctypes.c_double)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.