Search code examples
pythonctypes

How to translate C double two-dim data using python ctypes?


I try use python ctypes call a dll and translate api in python code. But I meet a function that have two-dimensional array and I dont know how to translate it now.I had forgot my C++&C language. TCHAR is a type like this char *p.

show in red rectangle.

enter image description here


Solution

  • .argtypes for the function would be:

    lmc1_AddCurveToLib.argtypes = POINTER(c_double * 2), c_int, c_char_p, c_int, c_int
    

    Here's a complete example:

    test.c

    #include <windows.h>
    #include <stdio.h>
    
    #ifdef _WIN32
    #   define API __declspec(dllexport)
    #else
    #   define API
    #endif
    
    API int lmc1_AddCurveToLib(double ptBuf[][2], int ptNum, TCHAR* pEntName, int nPenNo, BOOL bHatch) {
        printf("%s %d %d\n", pEntName, nPenNo, bHatch);
        for(int i = 0; i < ptNum; i++)
            printf("ptBuf[%d][0] = %lf, ptBuf[%d][1] = %lf\n", i, ptBuf[i][0], i, ptBuf[i][1]);
        return 123;
    }
    

    test.py

    import ctypes as ct
    
    dll = ct.CDLL('./test')
    # POINTER(c_double * 2) is equivalent to C (*double)[2] or double[][2], "A pointer to two doubles".
    dll.lmc1_AddCurveToLib.argtypes = ct.POINTER(ct.c_double * 2), ct.c_int, ct.c_char_p, ct.c_int, ct.c_int
    dll.lmc1_AddCurveToLib.restype = ct.c_int
    
    # C equivalent: double arr[3][2] = {{1.1,2.2}, {3.3,4.4}, {5.5,6.6}};
    # Note that *2*3 below is required order and opposite of C to
    # achieve the same memory layout.
    arr = (ct.c_double * 2 * 3)((1.1,2.2),(3.3,4.4),(5.5,6.6))
    
    print(dll.lmc1_AddCurveToLib(arr, len(arr), b'SomeName', 5, True))
    

    Output:

    SomeName 5 1
    ptBuf[0][0] = 1.100000, ptBuf[0][1] = 2.200000
    ptBuf[1][0] = 3.300000, ptBuf[1][1] = 4.400000
    ptBuf[2][0] = 5.500000, ptBuf[2][1] = 6.600000
    123