A vector
is C compatible, but you need to pass the C caller (or ctypes) the address of the first element. That said, you'd have to hold on to the pointer to the vector
to free it later. I think you'll be better off using an array from the start. You can pass the function an int
out parameter to receive the length of the array. Since you're using new
to allocate, remember to catch a bad_alloc
exception should the allocation fail.
Personally, I'd use an array of structs instead an array of pointers, such that the data is in single contiguous block. This yields a cleaner interface in ctypes. With an array of pointers you have to dereference twice to get at the struct.
C++:
#include <new>
#include <cwchar>
typedef struct myStruct {
wchar_t *id;
wchar_t *content;
wchar_t *message;
} myStruct;
const wchar_t ID[] = L"some id";
const wchar_t CONTENT[] = L"some content";
const wchar_t MESSAGE[] = L"some message";
DLLAPI myStruct **DLLApiGetArray(int *size)
{
int i, n = 5;
myStruct **result;
try {
result = new myStruct *[n];
for(i = 0; i < n; i++) {
myStruct *tmp = new myStruct();
tmp->id = new wchar_t[wcslen(ID) + 1];
tmp->content = new wchar_t[wcslen(CONTENT) + 1];
tmp->message = new wchar_t[wcslen(MESSAGE) + 1];
wcscpy(tmp->id, ID);
wcscpy(tmp->content, CONTENT);
wcscpy(tmp->message, MESSAGE);
result[i] = tmp;
}
} catch (std::bad_alloc &ba) {
*size = -1; return NULL;
}
*size = n; return result;
}
Python:
from ctypes import *
class myStruct(Structure):
_fields_ = [
("id", c_wchar_p),
("content", c_wchar_p),
("message", c_wchar_p)
]
myDLL = cdll.myDLL
myDLL.DLLApiGetArray.restype = POINTER(POINTER(myStruct))
myDLL.DLLApiGetArray.argtypes = [POINTER(c_int)]
n = c_int()
p = myDLL.DLLApiGetArray(byref(n))
n = n.value
Example looping through the result:
>>> for i in range(n):
... print i, p[i][0].id
...
0 some id
1 some id
2 some id
3 some id
4 some id
FYI, it's incorrect to use the _T
macro with explicit wchar_t
arrays. That's for Microsoft's TCHAR
type, for compiling as ANSI vs Unicode. Use L"wide character string literals"
.