1

My C function is:

int cluster_info(char *remote_ip, struct NodeStatInfo ***info, int *node_count)
{

     /* dynamically creates an array of pointers to struct NodeStatInfo. */
      ...

     (*info) = (struct NodeStatInfo**)malloc( sizeof(struct NodeStatInfo*) * count );
     for(i=0; i< count; i++)
         (*info)[i] = (struct NodeStatInfo*)malloc( sizeof(struct NodeStatInfo) );

     ...
     *node_count = count;
     ...

}

I have tried in the following manner:

class NodeStatInfo(Structure):
    _fields_ = [('status', c_char*10),
                ('name', c_char*64) ]

NodeStatInfoPtrType = ctypes.POINTER(NodeStatInfo)
PtrToNodeStatInfoPtrType = ctypes.POINTER(NodeStatInfoPtrType)
node_info = PtrToNodeStatInfoPtrType()

sn_count = c_int(0)

lib.cluster_info( SOME_IP, pointer(node_info) , byref( sn_count ) )
print node_info[0][0].status

The last statement did not print complete value passed from C function.

1 Answer 1

2

I don't see a major problem. You should use byref instead of creating a full pointer and define argtypes, but what you have should work.

lib.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct _NodeStatInfo {
    char status[10];
    char name[64];
} NodeStatInfo;

int count = 3;

int cluster_info(char *remote_ip,
                 NodeStatInfo ***info,
                 int *node_count)
{
    int i;
    *info = (NodeStatInfo **)malloc(sizeof(NodeStatInfo *) * count);
    for(i = 0; i < count; i++) {
        (*info)[i] = (NodeStatInfo *)malloc(sizeof(NodeStatInfo));
        strcpy((*info)[i]->status, "init");
        sprintf((*info)[i]->name, "node%d", i); 
    }
    *node_count = count;
    return 0;
}

Python:

from ctypes import * 

class NodeStatInfo(Structure):
    _fields_ = [
        ('status', c_char * 10),
        ('name', c_char * 64)]

P_NodeStatInfo = POINTER(NodeStatInfo)
PP_NodeStatInfo = POINTER(P_NodeStatInfo)

lib = CDLL('./lib.so')
lib.cluster_info.argtypes = [c_char_p, 
                             POINTER(PP_NodeStatInfo), 
                             POINTER(c_int)]

Demo:

>>> SOME_IP = '192.168.1.1'
>>> node_info = PP_NodeStatInfo()
>>> sn_count = c_int(0)
>>> lib.cluster_info(SOME_IP, byref(node_info), byref(sn_count))
0

>>> [node_info[i][0].status for i in range(sn_count.value)]
['init', 'init', 'init']

>>> [node_info[i][0].name for i in range(sn_count.value)]
['node0', 'node1', 'node2']
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.