[英]Returning pointer on vector of pointers from C++ dll to Python
I have successfully returned pointer to struct(that contains wchar_t*
) from c++ dll into Python like this: C++ code: 我已成功将指向指针的指针(包含
wchar_t*
)从c ++ dll返回到Python,如下所示:C ++代码:
...
typedef struct myStruct{
wchar_t* id;
wchar_t* content;
wchar_t* message;
} myStruct;
DLLAPI myStruct* DLLApiGetStruct(){
myStruct* testStruct = new myStruct();
testStruct->id = _T("some id");
testStruct->content = _T("some content");
testStruct->message = _T("some message");
return testStruct;
}
Python code: Python代码:
class MyPyStruct(Structure):
_fields_ = [
("id", c_wchar_p),
("content", c_wchar_p),
("message", c_wchar_p)
]
...
...
myDLL = cdll.LoadLibrary('myDLL.dll')
myDLL.DLLApiGetStruct.restype = POINTER(MyPyStruct)
result = myDLL.DLLApiGetStruct().contents
print result.id, result.content, result. message# those are valid values
Ok, that works fine, the PROBLEM is that now I need to return pointer on vector of pointers to those structures. 好的,这很好, 问题是现在我需要在指向这些结构的指针的向量上返回指针。 I've tried this:
我已经试过了:
C++ code: C ++代码:
typedef std::vector<myStruct*> myVector;
...
DLLAPI myVector* DLLApiGetVector(){
myVector* testVektor = new myVector();
for(i=0; i< 5; i++){
myStruct* testStruct = new myStruct();
testStruct->id = _T("some id");
testStruct->content = _T("some content");
testStruct->message = _T("some message");
testVektor->push_back(testStruct);
}
return testVektor;// all values in it are valid
}
Python code: Python代码:
#I think that first and second lines are incorrect (is that proper way to make restype??): #我认为第一行和第二行不正确(这是进行restype的正确方法吗?):
vectorOfPointersType = (POINTER(DeltaDataStruct) * 5) #5 is number of structures in vector
myDLL.DLLApiGetVector.restype = POINTER(vectorOfPointersType)
vectorOfPointersOnMyStruct= myDLL.DLLApiGetVector.contents
for pointerOnMyStruct in vectorOfPointersOnMyStruct:
result = pointerOnMyStruct.contents
print result.id, result.content, result.message
Values in last row are NOT valid - it's some random parts of memory I guess. 最后一行中的值无效-我猜这是内存中的一些随机部分。 This is error I get:
这是我得到的错误:
UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-11: character maps to <undefined>
A vector
is C compatible, but you need to pass the C caller (or ctypes) the address of the first element. vector
与C兼容,但是您需要将第一个元素的地址传递给C调用者(或ctypes)。 That said, you'd have to hold on to the pointer to the vector
to free it later. 就是说,您必须保持指向
vector
的指针,以便稍后释放它。 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. 您可以将
int
out参数传递给函数,以接收数组的长度。 Since you're using new
to allocate, remember to catch a bad_alloc
exception should the allocation fail. 由于您使用
new
进行分配,因此请记住,如果分配失败,则会捕获bad_alloc
异常。
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.
这会在ctypes中产生更清晰的界面。 With an array of pointers you have to dereference twice to get at the struct.
使用指针数组,您必须取消引用两次才能获取该结构。
C++: 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. 仅供参考,将
_T
宏与显式wchar_t
数组一起使用是不正确的。 That's for Microsoft's TCHAR
type, for compiling as ANSI vs Unicode. 这适用于Microsoft的
TCHAR
类型,可编译为ANSI vs Unicode。 Use L"wide character string literals"
. 使用
L"wide character string literals"
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.