Передача объектов python в качестве аргументов функции C/C++ с использованием ctypes

У меня есть dll с функцией, которая принимает PyObject в качестве аргумента, что-то вроде

void MyFunction(PyObject* obj)
{
    PyObject *func, *res, *test;

    //function getAddress of python object
    func = PyObject_GetAttrString(obj, "getAddress");

    res = PyObject_CallFunction(func, NULL);
    cout << "Address: " << PyString_AsString( PyObject_Str(res) ) << endl;
}

и я хочу вызвать эту функцию в dll из python, используя ctypes

Мой код Python выглядит так

import ctypes as c

path = "h:\libTest"
libTest = c.cdll.LoadLibrary( path )

class MyClass:
    @classmethod
    def getAddress(cls):
        return "Some Address"

prototype = c.CFUNCTYPE(    
    c.c_char_p,                
    c.py_object
)

func = prototype(('MyFunction', libTest))

pyobj = c.py_object(MyClass)
func( c.byref(pyobj) )

есть некоторая проблема в моем коде Python, когда я запускаю этот код, я получаю сообщение вроде

WindowsError: исключение: чтение нарушения прав доступа 0x00000020

Любое предложение по улучшению кода Python будет оценено.


person Maverick    schedule 26.06.2012    source источник
comment
Я полагаю, что PyObject_GetAttrString(Class, "getAddress") на самом деле PyObject_GetAttrString(obj, "getAddress")? Я также предполагаю, что вы проверяете каждый результат функции, и ни один из них не является нулевым до cout <<?   -  person 9000    schedule 27.06.2012
comment
Да это опечатка. Спасибо. Я исправлю это. Кроме того, код C в порядке. У меня проблемы с частью Python. Передача указателя на объекты python из Python в эту функцию c. Как ?   -  person Maverick    schedule 27.06.2012
comment
Хм, не знаю точно, но думаю byref здесь не нужен. Я полагаю, что просто func(pyobj) должно работать. С помощью byref код C получает указатель на указатель.   -  person 9000    schedule 27.06.2012


Ответы (1)


Я внес следующие изменения в ваш код, и это сработало для меня, но я не уверен, что это 100% правильный способ сделать это:

  1. Используйте ПИФУНКТИП.
  2. Просто передайте объект класса python.

Например:

prototype = c.PYFUNCTYPE(    
    c.c_char_p,                
    c.py_object
)

func = prototype(('MyFunction', libTest))

func( MyClass )
person Mark Tolonen    schedule 27.06.2012
comment
Да, у меня тоже сработало, спасибо. Но не могли бы вы объяснить, в чем разница между c.PYFUNCTYPE и c.CFUNCTYPE. Откуда мне знать, какой из них выбрать? - person Maverick; 27.06.2012
comment
Я не мог найти многого в документации, кроме того, что она не освобождает GIL (глобальную блокировку интерпретатора). Поскольку ваша DLL использовала Python API и передавала объекты Python, это казалось хорошим выбором. - person Mark Tolonen; 27.06.2012