2013-12-25 4 views
1

Я пытаюсь вернуть структуру, чтобы я мог использовать ее в Python. Я начинающий программист, поэтому, пожалуйста, объясните мне, что я делаю неправильно. Мне удалось вернуть простые ctypes раньше (bool, unsigned int), но структура слишком сложна для меня. Это то, что у меня есть:Возвращение struct из C++ dll в Python

DLLAPI.h

#define DLLAPI extern "C" __declspec(dllexport) 
... 
DLLAPI myStruct* DLLApiGetStruct(); 

DLLAPI.cpp

EDIT1: вместо TString, тип структура членов в wchar_t * сейчас, но ошибка я получаю то же самое

... 
typedef struct myStruct{ 
    wchar_t* id; 
    wchar_t* content; 
    wchar_t* message; 
} myStruct; 

DLLAPI myStruct* DLLApiGetStruct(){ 
    myStruct* test = new myStruct(); 
    test->id = _T("some id"); 
    test->content = _T("some content"); 
    test->message = _T("some message"); 
    return test; 
} 

вот мой код Python:

... 
class TestStruct(Structure): 
    _fields_ = [ 
     ("id", c_wchar_p), 
     ("content", c_wchar_p), 
     ("message", c_wchar_p) 
     ] 
class SomeClass(object): 
    .... 
    def test(self): 
     myDLL = cdll.LoadLibrary('myDLL.dll') 
     myDLL.DLLApiGetStruct.restype = TestStruct 
     result = myDLL.DLLApiGetStruct() 
     print "result type: ", type(result) 
     print "-"*30 
     print "result: ",result 
     print "-"*30 
     print result.id # line 152 

это то, что я получаю:

result type: <class 'Foo.TestStruct'> 
    ------------------------------ 
    result: <Foo.TestStruct object at 0x027E1210> 
    ------------------------------ 
    Traceback (most recent call last): 
    .... 
    .... 
    .... 
    line 152, in test 
     print result.id 
    ValueError: invalid string pointer 0x00000002 

TString Я использовал это станд :: wstring

Если ввести в MyStruct быть указателями или что-то вместо TString? Пожалуйста, помогите мне, я потратил 5 дней, пытаясь сделать эту работу.

+0

@eryksun вы мой герой: D, пожалуйста, опубликуйте это как ответ, и я приму это – Aleksandar

+0

спасибо еще раз! – Aleksandar

ответ

3

Как объяснили другие, проблема с версией 1 вопроса является использование станд :: строка, которая не является допустимым типом для Interop.

Глядя на версию 2 вопроса, ваши объявления на C++ и Python не совпадают. Код C++ возвращает указатель на структуру, но код Python ожидает возврата структуры по значению.

Вы можете изменить либо C++, либо Python в соответствии с другим.

C++

DLLAPI myStruct DLLApiGetStruct() 
{ 
    myStruct result; 
    result.id = L"some id"; 
    result.content = L"some content"; 
    result.message = L"some message"; 
    return result; 
} 

Python

myDLL.DLLApiGetStruct.restype = POINTER(TestStruct) 

Очевидно, что вы должны применять только один из этих изменений!

Обратите внимание, что в коде C++ я решил использовать явные широкие строки с префиксом L, а не с макросом _T(). Бывшие совпадения wchar_t *, а последнее - то, что вы используете с TCHAR. Я бы не рекомендовал TCHAR в эти дни, если вам не нужна поддержка Win98.

+0

Я изменил код Python и Я также попытался изменить код C++, как вы предложили (верните структуру по значению), но я не могу построить dll ... Я получаю 'ошибка C2526: 'DLLApiGetStruct': функция C linkage не может return C++ class 'myStruct'' – Aleksandar

+1

Возвращение больших структур по значению является теневой областью. У разных компиляторов есть разные способы сделать это. Может быть неприятно. Должен сказать так в ответ. –

+1

@Aleksandar: компилятор не знает, что это простые старые данные (POD). Я думаю, что он будет успешно скомпилирован, если вы переместите определение 'myStruct' в заголовок перед декларацией DLLApiGetStruct. – eryksun

1

http://docs.python.org/3.1/library/ctypes.html

c_wchar_p содержит wchar_t *, не std::wstring

+0

Благодарим вас за ответ. Итак, можно ли даже получать строку на Python таким образом?Можете ли вы дать мне пример того, как это сделать? – Aleksandar

+0

см. ** EDIT1 ** – Aleksandar

1

Проблема заключается в том вы возвращаете структуру, содержащую std::string «S, но вы говорите Python, что типы являются указателями на wchar_t. Это имеет тот же эффект, что и на C++.

struct Foo 
{ 
    std::string id; 
    std::string content; 
    std::string message; 
}; 

struct Bar 
{ 
    wchar_t* id; 
    wchar_t* content; 
    wchar_t* message; 
}; 

Foo f; 
Bar* = reinterpret_cast<Bar*>(&f); 
+0

спасибо, что ответили. Я пробовал то, что вы предложили, это так: Я поместил 'struct Bar' в DLLAPI.cpp и изменил DLLAPI Bar * DLLApiGetStruct() {..... Bar * barStruct = reinterpret_cast (&test); return barStruct; ' Я получаю ту же ошибку в Python. – Aleksandar

+0

, чтобы избежать' reinterpret_cast' Я просто изменил типы элементов структуры на 'wchar_t *', взгляните на ** EDIT1 ** – Aleksandar

Смежные вопросы