Python / C API 相互调用

最近需要将库封装为python可调用的库。目前验证是可以直接使用静态库封装,如果想使用动态库,linux可以使用以下指令生成动态库。

ar -x mylib.a
gcc -shared *.o -o mylib.so

封装过程中遇到undefined reference to symbol '_ZTVN10__cxxabiv117__class_type_infoE类似问题,则需要将gcc改为g++就可以了。动态库的使用方法参考博客

以下所有问题都可以从python官网中文链接中找到问题答案,封装过程中参考了这个博客

第一个问题:python如何保存c指针,便于后续使用?

PyObject* result = PyLong_FromVoidPtr((void*)info);

将指针通过PyLong_FromVoidPtr来生成pyobject,这样就可以保存指针值。在下次调用时,需要这样使用:

PyObject* info;
if (! PyArg_ParseTuple(args, "O", &info))
    return NULL;

void* my_info = PyLong_AsVoidPtr(info);

通过pyarg_parsetuple的O选项将数值读出来,再通过PyLong_AsVoidPtr来获取之前保存的指针值。

第二个问题:如何获取python传递来的list内容?

PyObject* input_ptr;
if (! PyArg_ParseTuple(args, "O", &input_ptr))
    return NULL;

先解析获取list的指针,然后通过PyObject_Length获取list长度。

int input_length = PyObject_Length(input_ptr);
for(int i = 0; i < input_length; i++)
{
   PyObject* item;
   item = PyList_GetItem(input_ptr, i);
   if(!PyFloat_Check(item))
    	input_value[i] = 0.0;
   input_value[i] = (float)(PyFloat_AsDouble(item));
}

通过pylist_getItem获取list内容,然后通过pyFloat_AsDouble将pyobject内容转换为需要的float值。

第三个问题:如何将C中的值以list形式传递出去?

这个问题和第二个问题相反。

PyObject* wrap_Get_Output(PyObject* self, PyObject* args)
{
    PyObject* net_info; 
    int id, mem_size;
    if (! PyArg_ParseTuple(args, "Oii", &net_info, &id, &mem_size))
	return NULL;
    info* my_info = (info*)(PyLong_AsVoidPtr(net_info));
    float* output_ptr = (float*)my_info->output_buff[id];
    PyObject* ret_val = PyList_New(mem_size);
    int err = 0;
    for(int i = 0; i < mem_size; i++)
    {
    	PyObject* item;
    	item = PyFloat_FromDouble((double)output_ptr[i]);
    	err = PyList_SetItem(ret_val,(Py_ssize_t)i,item);
    	if(err == -1)
    	{
    	    printf("SetItem Error: list length = %d, set index = %d\n",mem_size,i);
    	    return NULL;
    	}
    }
    return ret_val;
}

先生成一个指定长度的list,然后将数据转换为pyobject,并将数据放入list中,该函数返回值为list。

第四个问题,如何通过关键字传递参数?

METH_VARARGS | METH_KEYWORDS

通过在methon设置key_words传递参数,例如:

{"test", (PyCFunction)wrap_test, METH_VARARGS | METH_KEYWORDS, "test"},

再通过PyArg_ParseTupleAndKeywords来解析参数,代码中设置kwlist表示关键字的列表。

PyObject* wrap_test(PyObject* self, PyObject* args, PyObject* kw)
{
    int a,b,c;
    char* kwlist[] = {"a","b","c", NULL};
    if (! PyArg_ParseTupleAndKeywords(args,kw, "iii",kwlist, &a, &b, &c))
        return NULL;
    printf("a = %d, b = %d, c = %d\n", a,b,c);
    return Py_BuildValue("ii", a+b,a+c);
}

以下代码测试可以看出确实是按照关键字传递参数了 

(res1,res2)=nntest.test(b=1,c= 10,a=2)
print res1
print res2

 当然如果在PyArg_ParseTupleAndKeywords的format"iii"中加|表示|后的参数都是可选参数;

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值