Вопрос

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.

Это было полезно?

Решение

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']
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top