Ответ 1
Чтобы извлечь аргумент из вызова вашего метода, вам нужно посмотреть на функции, описанные в Разбор аргументов и значений зданий, например PyArg_ParseTuple
. (Это, если вы только принимаете позиционные аргументы! Есть и другие аргументы с позиционным и ключевым словом и т.д.)
Объект, возвращаемый с PyArg_ParseTuple
, не имеет увеличенного количества ссылок. Для простых функций C вам, вероятно, не нужно беспокоиться об этом. Если вы взаимодействуете с другими функциями Python/C или если вы освобождаете блокировку глобального интерпретатора (то есть разрешаете потоки), вам нужно очень тщательно подумать об объектной собственности.
static PyObject *
_sayhello_obj(PyObject *self, PyObject *args)
{
PyObject *obj = NULL;
// How can I fill obj?
static char fmt_string = "O" // For "object"
int parse_result = PyArg_ParseTuple(args, fmt_string, &obj);
if(!parse_res)
{
// Don't worry about using PyErr_SetString, all the exception stuff should be
// done in PyArg_ParseTuple()
return NULL;
}
// Of course, at this point you need to do your own verification of whatever
// constraints might be on your argument.
Для вызова метода для объекта вам необходимо использовать PyObject_CallMethod
или PyObject_CallMethodObjArgs
, в зависимости от того, как вы создаете список аргументов и имя метода. И посмотрите мой комментарий в коде об объектной собственности!
Быстрое отступление просто для того, чтобы убедиться, что вы не настроитесь на падение позже. Если вы действительно хотите, чтобы строка была напечатана, вам лучше просто получить ссылку на объект и передать ее в PyObject_Print
. Конечно, возможно, это просто для иллюстрации, или вы знаете лучше, чем я делаю то, что вы хотите делать с данными;)
char s[1024];
// How can I fill s, from obj.getName() ?
// Name of the method
static char method_name = "getName";
// No arguments? Score! We just need NULL here
char method_fmt_string = NULL;
PyObject *objname = PyObject_CallMethod(obj, obj_method, method_fmt_string);
// This is really important! What we have here now is a Python object with a newly
// incremented reference count! This means you own it, and are responsible for
// decrementing the ref count when you're done. See below.
// If there a failure, we'll get NULL
if(objname == NULL)
{
// Again, this should just propagate the exception information
return NULL;
}
Теперь в разделе String/Bytes Objects существует ряд функций Concrete Objects Layer docs; используйте то, что лучше всего подходит вам.
Но не забывайте этот бит:
// Now that we're done with the object we obtained, decrement the reference count
Py_XDECREF(objname);
// You didn't mention whether you wanted to return a value from here, so let just
// return the "None" singleton.
// Note: this macro includes the "return" statement!
Py_RETURN_NONE;
}
Обратите внимание на использование Py_RETURN_NONE
и обратите внимание, что это не return Py_RETURN_NONE
!
PS. Структура этого кода в значительной степени продиктована личным стилем (например, ранними версиями, static char
форматированием строк внутри функции, инициализацией до NULL
). Надеюсь, важная информация достаточно ясна, кроме стилистических конвенций.