簡體   English   中英

從C ++ dll到Python的指針矢量返回指針

[英]Returning pointer on vector of pointers from C++ dll to Python

我已成功將指向指針的指針(包含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代碼:

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

好的,這很好, 問題是現在我需要在指向這些結構的指針的向量上返回指針。 我已經試過了:

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代碼:

#我認為第一行和第二行不正確(這是進行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

最后一行中的值無效-我猜這是內存中的一些隨機部分。 這是我得到的錯誤:

UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-11: character maps to <undefined>

vector與C兼容,但是您需要將第一個元素的地址傳遞給C調用者(或ctypes)。 就是說,您必須保持指向vector的指針,以便稍后釋放它。 我認為從一開始就使用數組會更好。 您可以將int out參數傳遞給函數,以接收數組的長度。 由於您使用new進行分配,因此請記住,如果分配失敗,則會捕獲bad_alloc異常。

就個人而言,我將使用結構數組而不是指針數組,以使數據位於單個連續的塊中。 這會在ctypes中產生更清晰的界面。 使用指針數組,您必須取消引用兩次才能獲取該結構。

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;
}

蟒蛇:

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

遍歷結果的示例:

>>> 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

僅供參考,將_T宏與顯式wchar_t數組一起使用是不正確的。 這適用於Microsoft的TCHAR類型,可編譯為ANSI vs Unicode。 使用L"wide character string literals"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM