Shobhit Puri
Shobhit Puri

Reputation: 26007

How to return char ** from C++ and fill it in a list in Python using ctypes?

I've been trying to return an array of strings from C++ to python a follows:

// c++ code
extern "C" char** queryTree(char* treename, float rad, int kn, char*name, char *hash){
    //.... bunch of other manipulation using parameters...

    int nbr = 3; // number of string I wish to pass
    char **queryResult = (char **) malloc(nbr* sizeof(char**));
    for (int j=0;j<nbr;j++){
        queryResult[j] = (char *) malloc(strlen(results[j]->id)+1);
        if(queryResult[j]){
            strcpy(queryResult[j], "Hello"); // just a sample string "Hello"
        } 
    }
    return queryResult;
}
// output in C++:
Hello
Hello
Hello

Following is the code in python:

libtest = ctypes.c_char_p * 3;
libtest = ctypes.CDLL('./imget.so').queryTree("trytreenew64", ctypes.c_float(16), ctypes.c_int(20), ctypes.c_char_p(filename), ctypes.c_char_p(hashval))
print libtest

output in python is integer :?

I am novice in python. I know I am doing something wrong at python side. I've been looking at some other questions where they are passing a char* but I was not able to get it working for char**. I've trying for hours. Any help would be appreciated.

19306416

Upvotes: 1

Views: 1928

Answers (1)

tdelaney
tdelaney

Reputation: 77337

The ctypes doc says: "By default functions are assumed to return the C int type. Other return types can be specified by setting the restype attribute of the function object."

This should work:

(edited to add POINTER)

imget = ctypes.CDLL('./imget.so')
imget.queryTree.restype = ctypes.POINTER(ctypes.c_char_p * 3)
imget.queryTree.argtypes = (ctypes.c_char_p, ctypes.c_float, ctypes.c_int,
    ctypes.c_char_p, ctypes.c_char_p)
libtest = imget.queryTree("trytreenew64",16, 20, filename, hashval)

Upvotes: 6

Related Questions